VC++编程常见问题解答十四 问:如何控制菜单的大小? 我用MFC的CMenu生成了一个动态菜单(例如File,Edit,View...Help), 我想控制这 个菜单的大小(长+高). 答1:查找 WM_MEASUREITEM 和 MEASUREITEMSTRUCT. 答2:查询系统::GetSystemMetric(SM_CXMENUSIZE). 我从新闻组得到下面一个例子: // 你可以通过如下代码来获得文本的大小: //(A)获得被使用的字体 NONCLIENTMETRICS ncm; HFONT hFontMenu; SIZE size; size.cx = size.cy = 0; memset(&ncm, 0, sizeof(NONCLIENTMETRICS)); ncm.cbSize = sizeof(NONCLIENTMETRICS); if (SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0)) { hFontMenu = CreateFontIndirect(&ncm.lfMenuFont); //(B) 获得菜单项的文本: char szText[_MAX_PATH]; pMenu->GetMenuString(0, szText, _MAX_PATH, MF_BYPOSITION); //然后,获得菜单项文本的高度: HFONT hFontOld; HDC hDC; hDC = ::GetDC(NULL); hFontOld = (HFONT) ::SelectObject(hDC, hFontMenu); GetTextExtentPoint32(hDC, szText, lstrlen(szText), &size); SelectObject(hDC, hFontOld); ::ReleaseDC(NULL, hDC); } /* 此时,size.cy即为高度,size.cx为宽度,你可以给菜单加上自定义的高度 和宽度,通过比较,我发现宽度为4比较合适。 */ 问:改变LVIS_SELECTED的状态颜色? 我想将CListCtrl项和CTreeCtrl项在LVIS_SELECTED状态时的颜色变灰. A1:查找函数CustomDraw,它是IE4提供的公共控制,允许自己写代码. A2:生成一个draw控件,然后在DrawItem中处理文本颜色. 问:如何只存储文档的某一部分? 我只想存储文档的某一部分,能否象使用文件一样使用文档?(也就是有定位函数). 答:将每个CArchive类设置为CFile类的派生类,这样你就能使用Seek等成员函数. 问:保存工具条菜单有bug吗? 使用浮动菜单条时,SaveBarState和LoadBarState出现了问题.如果菜单是浮动 的,重起应用程序时它会出现在左上角,而它固定在屏幕其它位置时,下一次启动 就会出现在该位置,这是什么原因? 答:你试试这个PToolBar->Create(this,...,ID_MYTOOLBAR); 你的工具条需要包括id,而不是象默认的工具条那样. 问:Tip of the day的bug 我创建了一个简单的mdi应用程序,使用.BSF(自定义的文档扩展名)作为它的文档 我保存一个foo.bsf文档后,可以在资源管理器中双击该文件打开mdi应用程序 同时打开foo.bsf文档. 但当我给mdi应用程序加上a tip of the day组件之后,从资源管理器中双击foo.bsf 后,就会给我一个警告:ASSERT(::IsWindow(m_hWnd)),然后mdi应用程序就死那了. 答:当从dde启动应用程序(例如:双击相关文档)时,"Tip of the Day"是有bug的. 你可以看看函数"ShowTipAtStartup",它在"InitInstance"中调用,可以看到 tip of the day作为一个模式对话框显示,在处理其它消息时它一直进行消息循环 你可心修改ShowTipAtStartup使其从dde启动时不出现tip of the day. void CTipOfApp::ShowTipAtStartup(void) { // CG: This function added by 'Tip of the Day' component. CCommandLineInfo cmdInfo; ParseCommandLine(cmdInfo); if (cmdInfo.m_bShowSplash && cmdInfo.m_nShellCommand != CCommandLineInfo::FileDDE) { CTipDlg dlg; if (dlg.m_bStartup) dlg.DoModal(); } } 如果还有其它bug,你可以设定cmdInfo.m_nShellCommand的过滤. 问:如何让我的mfc应用程序可以在最上面? 如何可以让我的程序可以显示在其它的窗口上面? 答:让用户选择"总是在最上面"最好是在系统菜单里加入一个选项.可以通过修改 WM_SYSCOMMAND消息来发送用户的选择.菜单的命令标识(id)会作为一个参数 传给OnSysCommand(). 要定义标识(id),将如下代码加入到CMainFrame.CPP中: #define WM_ALWAYSONTOP WM_USER + 1 将"总在最上面"的菜单项加入到系统菜单中,将如下代码加入到函数CMainFrame::OnCreate()中: CMenu* pSysMenu = GetSystemMenu(FALSE); pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, WM_ALWAYSONTOP,"&Always On Top"); 使用ClassWizard,加入对WM_SYSCOMMAND消息的处理,你应该改变消息过滤器, 使系统可以处理这个消息. void CMainFrame::OnSysCommand(UINT nID, LPARAM lParam) { switch ( nID ) { case WM_ALWAYSONTOP: if ( GetExStyle() & WS_EX_TOPMOST ) { SetWindowPos(&wndNoTopMost, 0, 0, 0, 0,SWP_NOSIZE | SWP_NOMOVE); GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,MF_UNCHECKED); } else { SetWindowPos(&wndTopMost, 0, 0, 0, 0,SWP_NOSIZE | SWP_NOMOVE); GetSystemMenu(FALSE)->CheckMenuItem(WM_ALWAYSONTOP,MF_CHECKED); } break; default: CFrameWnd::OnSysCommand(nID, lParam); } }