// This example illustrates extending the framework's standard command // route from the view to objects managed by the view. This example // is from an object-oriented drawing application, similar to the // DRAWCLI sample application, which draws and edits "shapes".
BOOL CMyView::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) { // Extend the framework's command route from the view to // the application-specific CMyShape that is currently selected // in the view. m_pActiveShape is NULL if no shape object // is currently selected in the view. if ((m_pActiveShape != NULL) && m_pActiveShape->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)) return TRUE;
// If the object(s) in the extended command route don't handle // the command, then let the base class OnCmdMsg handle it. return CView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo); }
// The command handler for ID_SHAPE_COLOR (menu command to change // the color of the currently selected shape) was added to // the message map of CMyShape (note, not CMyView) using ClassWizard.
// The menu item will be automatically enabled or disabled, depending // on whether a CMyShape is currently selected in the view, that is, // depending on whether CMyView::m_pActiveView is NULL. It is not // necessary to implement an ON_UPDATE_COMMAND_UI handler to enable // or disable the menu item.
OSVERSIONINFO info; memset((char*)&info, 0, sizeof(OSVERSIONINFO)); info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if(GetVersionEx(&info)) { //we don't run on Win32s, so check only two values if(info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { //On windows 95 m_cx = GetSystemMetrics(SM_CXFIXEDFRAME); m_cy = GetSystemMetrics(SM_CYFIXEDFRAME); } else { //On NT m_cx = GetSystemMetrics(SM_CXDLGFRAME); m_cy = GetSystemMetrics(SM_CYDLGFRAME); } } }
说明:
1)WM_ACTIVATE消息在ClassWizard中没有,按如下步骤添加,右击CMyDlg类,选Add Windows Message
Handle,接着在Filter for messages available to中选Window,在New Windows
messages/events列表中就会出现WM_ACTIVATE,选中,点击Add Handler 2)SM_CXDLGFRAME,SM_CYDLGFRAME NT中取得有WS_DLGFRAMEstyle风格的窗口的高和宽 95中已经废弃而采用SM_CX_FIXEDFRAME和SM_CYFIXEDFRAME
44. 初始化应用程序的大小
如果想使应用程序界面(文档)在开始运行是按你的尺寸展现在屏幕上, 添加代码如下: BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs) { int xsize=::GetSystemMetrics(SM_CXSCREEN); int ysize=::GetSystemMetrics(SM_CYSCREEN); cs.cx=xsize*5/10; cs.cy=ysize*5/10; cs.x=(xsize-cs.cx)/2; cs.y=(ysize-cs.cy)/2;
[问题提出] 如何在串太长时往让其末尾显示一个省略号(在SDI或MDI的View中)? [程序实现] 建立名为My的SDI或MDI工程. void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here
pDC->DrawText(CString("It's a long string,so we will add a '...'
at the end."),CRect (110, 110, 180, 130),DT_LEFT | DT_END_ELLIPSIS); //Add ellpsis to middle of string if it does not fit
pDC->DrawText(CString("It's a long string,so we will add a '...'
at the end."),CRect (110, 140, 300, 160),DT_LEFT | DT_PATH_ELLIPSIS); } 51. 如何获得其他程序的图标,并显示在View中
// TODO: Add your message handler code here // Do not call CView::OnPaint() for painting messages } 说明:_T("NotePad.exe")指的是要获得什么程序的图标. 或者在OnDraw()中(此时必须保证没有OnPaint()函数,想想为何?) void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument(); ASSERT_VALID(pDoc); // TODO: add draw code for native data here HICON hIcon=:: ExtractIcon(AfxGetInstanceHandle(),_T("NotePad.exe"),0); if (hIcon &&hIcon!=(HICON)-1) pDC->DrawIcon(10,10,hIcon); }
int GetDeviceCaps( HDC hdc, // handle to DC int nIndex // index of capability ); ///得到屏幕尺寸的代码如下 void CMyDlg::OnPaint() { CPaintDC dc(this); int cx = ::GetDeviceCaps(dc.m_hDC,HORZRES);///得到宽度 int cy = ::GetDeviceCaps(dc.m_hDC,VERTRES);///得到高度 CDialog::OnPaint();
// base case . . .if directory exists if(GetFileAttributes(strDir)!=-1) return;
// recursive call, one less directory int nFound = strDir.ReverseFind('\\'); CreateAllDirectories(strDir.Left(nFound));
// actual work CreateDirectory(strDir,NULL); } 68. ReverseFind() #include #include int main() { CString s; s.Format("abcdefghijk"); int nPos = s.ReverseFind('a'); printf("nPos is %d\n",nPos); return 0; } 其中,'a'对应的nPos是0,'h'对应的nPos是7,以此类推。但是:s.ReverseFind('a')和s.Find('a')的结果是一样的。 问题是:ReverseFind() 和 Find() 有什么区别呢: 对于ReverseFind(),查找顺序是从后往前,找到后的nPos是按前后顺序排列的。 而Find()是从前往后查的,找到后的nPos也是按前后顺序排列的。 69. MDI中如何只屏蔽掉子框架的右上角的关闭按钮 int CChildFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1) return -1; 。。。 CMenu* pSysMenu = GetSystemMenu(FALSE); pSysMenu->EnableMenuItem(SC_CLOSE,MF_BYCOMMAND |MF_DISABLED|MF_GRAYED); return 0; } 70. 程序如何删除自己 /////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE h, HINSTANCE b, LPSTR psz, int n) {
// Is this the Original EXE or the clone EXE? // If the command-line 1 argument, this is the Original EXE // If the command-line >1 argument, this is the clone EXE
if (__argc == 1) {
// Original EXE: Spawn clone EXE to delete this EXE // Copy this EXEcutable image into the user''s temp directory
//***注意了***: // Open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL, OPEN_EXISTI NG, FILE_FLAG_DELETE_ON_CLOSE, NULL);
// Spawn the clone EXE passing it our EXE''s process handle // and the full path name to the Original EXE file. TCHAR szCmdLine[512]; HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE, TRUE, GetCurrentProcessId());
// This original process can now terminate. } else { // Clone EXE: When original EXE terminates, delete it HANDLE hProcessOrig = (HANDLE) _ttoi(__targv[1]); WaitForSingleObject(hProcessOrig, INFINITE); CloseHandle(hProcessOrig); DeleteFile(__targv[2]); // Insert code here to remove the subdirectory too (if desired).
// The system will delete the clone EXE automatically // because it was opened with FILE_FLAG_DELETE_ON_CLOSE } return(0); } 这一段程序思路很简单:不是不能在运行时直接删除本身吗?好,那么程序先复制(CLONE)一个自己,用复制品起动另一个进程,然后自己结束运行,则原来的EXE文件不被系统保护.这时由新进程作为杀手删除原来的EXE文件,并且继续完成程序其他的功能。
新进程在运行结束后,复制品被自动删除。这又是值得介绍的一个把戏了,注意:
// Open the clone EXE using FILE_FLAG_DELETE_ON_CLOSE HANDLE hfile = CreateFile(szPathClone, 0, FILE_SHARE_READ, NULL,OPEN_EXISTIN G, FILE_FLAG_DELETE_ON_CLOSE, NULL);
这里面的FILE_FLAG_DELETE_ON_CLOSE标志,这个标志是告诉操作系统,当和这个文件相关的所有句柄都被关闭之后(包括上面这个
CREATEFILE创建的句炳),就把这个文件删除。几乎所有的临时文件在创建时,都指明了这个标志。另外要注意的是:在复制品进程对原始程序操刀之
前,应该等待原进程退出.在这里用的是进程同步技术.用HANDLE hProcessOrig = OpenProcess(SYNCHRONIZE,
TRUE,GetCurrentProcessId());得到原进程句柄.SYNCHRONICE标志在NT下有效,作用是使OpenProcess得
到的句柄可以做为同步对象.复制品进程用WaitForSingleObject函数进行同步,然后一个DeleteFile,以及进行其它销毁证据(比
如删目录)的工作,一切就完事了。
InitInstance() { . ... //instead of adding CSingleDocTemplate // Add CMultiDocTemplate. pDocTemplate = new CMultiDocTemplate( IDR_MAINFRAME, RUNTIME_CLASS(CSDIDoc), RUNTIME_CLASS(CChldFrm), // For Main MDI Frame change this frame window from // CFrameWnd derivative ( i.e. CMainFrame ) // to your CMDIChildWnd derived CChldFrm. RUNTIME_CLASS(CSDIView)); /// After this it is required to create the main frame window // which will contain all the child windows. Now this window is // what was initially frame window for SDI. CMainFrame* pMainFrame = new CMainFrame; if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE; m_pMainWnd = pMainFrame; ..... } 在从CMDIFrameWnd中继承的类CMainFrame代替CFramWnd后,所有的类都将从CMDIFrame继承,而不是CFrameWnd,编译运行后你就会发现程序已经从SDI变换到MDI。 注意:在CMainFram中必须将构造函数从private改为public.否则会出错。
80. CDC中的竖排文本?
在OnDraw成员函数中我想让文本竖直对齐,但CDC类似乎不支持该处理 方法一:如果你的竖直对齐是指旋转文本的话,下面的代码会对你有帮助:该代码检查一个Check box控制,查看文本是否需要旋转. // m_pcfYTitle is a CFont* to the selected font. // m_bTotateYTitle is a bool (==TRUE if rotated) void CPage1::OnRotateytitle() { LOGFONT lgf; m_pcfYTitle->GetLogFont(&lgf); m_bRotateYTitle= ((CButton*)GetDlgItem(IDC_ROTATEYTITLE))->GetCheck()>0; // escapement is reckoned clockwise in 1/10ths of a degree: lgf.lfEscapement=-(m_bRotateYTitle*900); m_pcfYTitle->DeleteObject(); m_pcfYTitle->CreateFontIndirect(&lgf); DrawSampleChart(); } 注意如果你从CFontDialog中选择了不同的字体,你应该自己设定LOGFONT的lfEscapement成员.将初始化后的lfEscapement值传到CFontDialog中. 方法二:还有一段代码可参考: LOGFONT LocalLogFont; strcpy(LocalLogFont.lfFaceName, TypeFace); LocalLogFont.lfWeight = fWeight; LocalLogFont.lfEscapement = Orient; LocalLogFont.lfOrientation = Orient; if (MyFont.CreateFontIndirect(&LocalLogFont)) { cMyOldFont = cdc->SelectObject(&MyFont); }
81. 如何用键盘滚动分割的视口?
我的问题是当我用鼠标滚动分割窗口时,视口滚动都很正常,但用键盘时,却什么也没有发生. 在你的视图继承类中加入如下两个函数,假定该类为CScrollerView: void CScrollerView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) { BOOL processed; for (unsigned int i=0;i< nRepCnt&&processed;i++) processed=KeyScroll(nChar); if (!processed) CScrollView::OnKeyDown(nChar, nRepCnt, nFlags); } BOOL CScrollerView::KeyScroll(UINT nChar) { switch (nChar) { case VK_UP: OnVScroll(SB_LINEUP,0,NULL); break; case VK_DOWN: OnVScroll(SB_LINEDOWN,0,NULL); break; case VK_LEFT: OnHScroll(SB_LINELEFT,0,NULL); break; case VK_RIGHT: OnHScroll(SB_LINERIGHT,0,NULL); break; case VK_HOME: OnHScroll(SB_LEFT,0,NULL); break; case VK_END: OnHScroll(SB_RIGHT,0,NULL); break; case VK_PRIOR: OnVScroll(SB_PAGEUP,0,NULL); break; case VK_NEXT: OnVScroll(SB_PAGEDOWN,0,NULL); break; default: return FALSE; // not for us // and let the default class // process it. } return TRUE; }
82. 如何改变默认的光标形状?
我试着将光标改变为其它的形状和颜色,但却没有变化. 在对话框/窗口/你需要的地方加上对WM_SETCURSOR消息的处理. BOOL MyDialog::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) { // TOD Add your message handler code here and/or call default ::SetCursor(AfxGetApp()->LoadCursor(IDC_MYCURSOR)); return TRUE; //return CDialog::OnSetCursor(pWnd, nHitTest, message); } 你没有成功的原因是因为窗口类光标风格不能为NULL.
83. 如何选择CTreeCtrl中的节点文本进行编辑?
在向CTreeCtrl中加入一项后,有什么方法可以编辑该节点的文本呢? 首先设置你的CcompTreeCtrl具有TVS_EDITLABELS属性.在设计时用控件属性来设置在运行时用GetStyle()/SetStyle()成员函数来设置.然后请看下述代码: HTREEITEM CCompTreeCtrl::AddSet() { static int setCnt =3D 1; HTREEITEM hItem; CString csSet; //create text for new note: New Set 1, New Set 2 ... csSet.Format( _T( "New Set %d" ), setCnt++ ); hItem =3D InsertItem( csSet, IMG_CLOSEDFOLDER, IMG_CLOSEDFOLDER ); if( hItem !=3D NULL ) EditLabel( hItem ); return hItem; }
88. How do I update the text of a pane in a status bar?
By
default, a CStatusBar pane is not enabled when the pane is created. To
activate a pane, you must call the ON_UPDATE_COMMAND_UI() macro for each
pane on the status bar and update the panes. Because panes do not send
WM_COMMAND messages, you cannot use ClassWizard to activate panes; you
must type the code manually. For example, suppose one pane has
ID_INDICATOR_PAGE as its identifier and that it contains the current
page number in a document. To make the ID_INDICATOR_PAGE pane display
text, add the following to a header file (probably the MAINFRM.H file):
To
display text in the panes, either call SetPaneText() or call
CCmdUI::SetText() in the OnUpdate() function. For example, you might
want to set up an integer variable m_nPage that contains the current
page number. Then, the OnUpdatePage() function might read as follows: