本文共 15304 字,大约阅读时间需要 51 分钟。
(1) 为什么即使调用EnableMenuItem菜单项后,菜单项还处于禁止状态
需要将CFrameWnd:: m_bAutomenuEnable设置为FALSE,如果该数据成员为TRUE(缺省值),工作框将自动地禁止没有ON_UPDATE_COMMAND_UI或者ON_COMMAND的菜单项。 //Disable MFC from automatically disabling menu items. m_bAuoMenuEnable=FALSE //Now enable the menu item. CMenu* pMenu=GetMenu () ASSERT_VALID (pMenu) pMenu->EnableMenuItem (ID_MENU_ITEM,MF_BYCOMMAND | MF_ENABLED)
(2) 如何给系统菜单添加一个菜单项
给系统菜单添加一个菜单项需要进行下述三个步骤: 首先,使用Resource Symbols对话(在View菜单中选择Resource Symbols...可以显示该对话)定义菜单项ID,该ID应大于0x0F而小于0xF000; 其次,调用CWnd::GetSystemMenu获取系统菜单的指针并调用CWnd:: Appendmenu将菜单项添加到菜单中。下例给系统菜单添加两个新的 int CMainFrame:: OnCreate (LPCREATESTRUCT lpCreateStruct) { … //Make sure system menu item is in the right range. ASSERT (IDM_MYSYSITEM &0xFFF0)==IDM_MYSYSITEM) ASSERT (IDM-MYSYSITEM<0xF000) //Get pointer to system menu. CMenu* pSysmenu=GetSystemmenu (FALSE) ASSERT_VALID (pSysMenu) //Add a separator and our menu item to system menu. CString StrMenuItem (_T ("New menu item")) pSysMenu->Appendmenu (MF_SEPARATOR) pSysMenu->AppendMenu (MF_STRING, IDM_MYSYSITEM, strMenuitem) … } 现在,选择系统菜单项时用户应进行检测。使用ClassWizard处理WM_SYSCOMMAND消息并检测用户菜单的nID参数: void CMainFrame:: OnSysCommand (UINT nID,LPARAM lParam) { //Determine if our system menu item was selected. if ( (nID & 0xFFF0)==IDM_MYSYSITEM) { //TODO-process system menu item } else CMDIFrameWnd ::OnSysCommand (nID, lParam) } 最后,一个设计良好的UI应用程序应当在系统菜单项加亮时在状态条显示一个帮助信息,这可以通过增加一个包含系统菜单基ID的串表的入口来实现。
(3) 如何确定顶层菜单所占据的菜单行数
这可以通过简单的减法和除法来实现。首先,用户需要计算主框窗口的高度和客户区;其次,从主框窗口的高度中减去客户区、框边界以及标题的高度;最后,除以菜单栏的高度。下例成员函数是一个计算主框菜单所占据的行数的代码实现。 int CMainFrame:: GetMenuRows () { CRect rcFrame,rcClient GetWindowRect (rcFrame) GetClientRect (rcClient) return (rcFrame.Height () -rcClient.Height () - :: GetSystemMetrics(SM_CYCAPTION) - (:: getSystemMetrics(SM_CYFRAME) *2)) / :: GetSystemMetrics(SM_CYMENU) }
(4) 在用户环境中如何确定系统显示元素的颜色
调用SDK函数GetSysColor可以获取一个特定显示元素的颜色。下例说明了如何在MFC函数CMainFrameWnd:: OnNcPaint中调用该函数设置窗口标题颜色。 void CMiniFrameWnd:: OnNcPaint () { … dc.SetTextColor (:: GetSysColor (m_bActive ? COLOR_CAPTIONTEXT : COLOR_INACTIVECAPTIONTEXT)) …
(5) 如何查询和设置系统参数
在Windows 3.1 SDK中介绍过SDK函数SystemParametersInfo,调用该函数可以查询和设置系统参数,诸如按键的重复速率设置、鼠标双击延迟时间、图标字体以及桌面覆盖位图等等。 //Create a font that is used for icon titles. LOGFONT stFont ∶: SystemParametersInfo (SPIF_GETICONTITLELOGFONT, sizeof (LOGFONT), &stFont, SPIF_SENDWININICHANGE) m_font.CreateFontIndirect (&stFont) //Change the wallpaper to leaves.bmp. ∶ : SystemParametersInfo (SPI_SETDESKWALLPAPER, 0, _T (" forest.bmp"), SPIF_UPDATEINIFILE)
(6) 如何确定当前屏幕分辨率
调用SDK函数GetSystemMetrics,该函数可以检索有关windows显示信息,诸如标题大小、边界大小以及滚动条大小等等。 //Initialize CSize object with screen size. CSize sizeScreen (GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN))
(7) 如何使用一个预定义的Windows光标
调用CWinApp:: LoadStandardCursor并传送光标标识符。 BOOL CSampleDialog:: OnSetCursor (CWnd* pWnd, UINT nHitTest, UINT message) { //Display wait cursor if busy. if (m_bBusy) { SetCursor (AfxGetApp () ->LoadStandardCursor (IDC_WAIT)) return TRUE } return CDialog:: OnSetCursor (pWnd. nHitTest,message) }
(8) 如何检索原先的Task Manager应用程序使用的任务列表
原 先的Task Manager应用程序显示顶层窗口的列表。为了显示该列表,窗口必须可见、包含一个标题以及不能被其他窗口拥有。调用CWnd:: GetWindow可以检索顶层窗口的列表,调用IsWindowVisible、GetWindowTextLength以及GetOwner可以确定 窗口是否应该在列表中。下例将把TaskManager窗口的标题填充到列表中。 void GetTadkList (CListBox&list) { CString strCaption //Caption of window. list.ResetContent () //Clear list box. //Get first Window in window list. ASSERT_VALID (AfxGetMainWnd ()) CWnd* pWnd=AfxGetMainWnd () ->GetWindow (GW_HWNDFIRST) //Walk window list. while (pWnd) { // I window visible, has a caption, and does not have an owner? if (pWnd ->IsWindowVisible() && pWnd ->GetWindowTextLength () &&! pWnd ->GetOwner ()) { //Add caption o window to list box. pWnd ->GetWindowText (strCaption) list.AddString (strCaption) } //Get next window in window list. pWnd=pWnd ->GetWindow(GW_HWNDNEXT) } }
(9) 如何确定Windows和Windows系统目录
有两个SDK函数可以完成该功能。GetWindowsDirectory和GetSystemDirectory,下例说明了如何使用这两个函数: TCHAR szDir [MAX_PATH] //Get the full path of the windows directory. ∶ : GetWindowsDirectory (szDir, MAX_PATH) TRACE ("Windows directory %s/n", szDir) //Get the full path of the windows system directory. ∶ : GetSystemDirectory (szDir, MAX_PATH) TRACE ("Windows system directory %s/n", szDir)
(10) 在哪儿创建临文件
调用SDK函数GetTemPath可以确定临时文件的目录,该函数首先为临时路径检测TMP环境变量:如果没有指定TMP,检测TMP环境变量,然后返回到当前目录。下例说明了如何创建一个临时文件。 … //get unique temporary file. CString strFile GetUniqueTempName (strFile) TRY { //Create file and write data.Note that file is closed //in the destructor of the CFile object. CFile file (strFile,CFile ::modeCreate | CFile:: modeWrite) //write data } CATCH (CFileException, e) { //error opening file } END_CATCH … Void GetuniqueTempName (CString& strTempName) { //Get the temporary files directory. TCHAR szTempPath [MAX_PATH] DWORD dwResult=:: GetTempPath (MAX_PATH, szTempPath) ASSERT (dwResult) //Create a unique temporary file. TCHAR szTempFile [MAX_PATH] UINT nResult=GetTempFileName (szTempPath, _T ("~ex"),0,szTempfile) ASSERT (nResult) strTempName=szTempFile }
(11) 我怎样才能建立一个等待光标?
调 用 BeginWaitCursor 函 数 来 启 动 等 待 光 标,调 用 EndWaitCursor 函 数 来 结 束 等 待 光 标。要 注 意,二 者 都 要 调 用 app 的 成 员 函 数,如 下 所 示: AfxGetApp()->BeginWaitCursor(); // 要做的事 AfxGetApp()->EndWaitCursor();
(12) 我在MDI框架中有个 form 视窗。它有个取消按钮,我需要当用户按取消按钮时可关闭form视窗。我应该如何关闭该文档?
调 用 OnCloseDocument 函 数。
(13) 如何访问桌面窗口
静态函数CWnd:: GetDesktopWindow 返回桌面窗口的指针。下例说明了MFC函数CFrameWnd::BeginModalStae是如何使用该函数进入内部窗口列表的。 void CFrameWnd::BeginModalState () { … //first count all windows that need to be disabled UINT nCount=0 HWND hWnd= :: GetWindow (:: GetDesktopWindow(), GW_CHILD) while (hWnd!=NULL) { if (:: IsWindowEnabled (hwnd) && CWnd::FromHandlePermanent (hWnd)!=NULL && AfxIsDescendant (pParent->m_hWnd, hWnd) && :: SendMessage (hWnd, WM_DISABLEMODAL, 0, 0)==0) { ++nCount } hWnd=:: GetWindow (hWnd, GW_HWNDNEXT) } …
( 14 ) 什么是 COLORREF? 我该怎样用它 ? COLORREF 是一个 32-bit 整型数值,它代表了一种颜色。你可以使用 RGB 函数来初始化 COLORREF 。例如: COLORREFcolor=RGB(0,255,0); RGB 函数接收三个 0-255 数值,一个代表红色,一个代表绿色,一个代表蓝色。在上面的例子中,红色和蓝色值都为 0 ,所以在该颜色中没有红色和蓝色。绿色为最大值 255 。所以该颜色为绿色。 0,0,0 为黑色, 255,255,255 为白色。 另一种初始化 COLORREF 的方法如下所示: CColorDialogcolorDialog; COLORREFcolor; if(colorDialog.DoModal()==IDOK) { color=colorDialog.GetColor(); } 这段代码使用了 MFC 中的颜色对话框,它需要文件。
( 15 ) AppWizard 所产生的 STDAFX 文件是干什么用的 ? 它主要是协助产生预编译头文件的。通常你是不需要修改它的。
( 16 ) 我在我的程序中是了 CDWordArray 。我向它添加了约 10,000 个整数,这使得它变得非常非常慢。为什么会这么糟 ? CDWordArray 是很好用的,只是因为你没有指定数组的最大尺寸。因此,当你添加新元素时,该类会从堆中重新分配空间。不幸的是,该类会在每次插入新元素时都为数组重新分配空间。如果你向它添加了很多新元素,所有这些分配和复制数组的操作会就会使它变慢。解决该问题的方法是,你可以使用 SetSize 函数的第二个参数来改变这种重新分配的频率。例如,如果你把该参数设置为 500 ,则每次数组空间超出时它才重新分配并添加 500 个新空间,而不是 1 个。这样一来,你就可以不用重新分配而添加了另外 499 个元素空间,这也会大大提高程序的运行速度。
( 17 ) 我该如何改变 MDI 框架窗口的子窗口的大小以使在窗口以一定的大小打开 ? 在视中的 OnInitialUpdate 函数中调用 GetParentFrame 函数。 GetParentFrame 会返回一指向一保存有该视的框架窗口的指针。然后调用在框架窗口上调用 MoveWindow 。
(1 8 )在我的程序的某些部分,我可以调用 MessageBox 函数来建立一个信息对话框,例如在视类中。但是,在其它部分我却不能,如文档类中。为什么?我怎样才能在我的应用程序类中建立一个信息对话框? MessageBox 函数来自 CWnd 类,所以你只能在从 CWnd 继承的类 ( 如 CView) 中调用它。但是, MFC 也提供了 AfxMessageBox 函数,你可以在任何地方调用它。
( 19 ) 我需要在我的程序中设置全局变量,以使文档中的所有类都能访问。我应该吧它放到哪儿 ? 把该变量放到该应用程序类的头文件中的 attribute 处。然后,在程序的任何地方,你都可以用下面的方法来访问该变量: CMyApp*app=(CMyApp*)AfxGetApp(); app->MyGlobalVariable=...
(2 0 ) 我听说 MFC 可以发现内存漏洞,我怎样使用该特性 ? 如果你在 Debug 菜单中的 Go 选项 ( 不是 Project 菜单中的 Execute 选项 ) 来运行你的应用程序, MFC 应该在程序终止时报告内存漏洞。如果没有,那么试试运行 MFCTracer 工具程序 ( 在 VC++ 程序组中 ) ,并启动跟踪。然后返回应用程序。
(2 1 ) 我怎样才能在我的应用程序中循环浏览已经打开的文档 ? 使用 CDocTemplate 中未公开的 GetFirstDocPosition() 和 GetNextDoc() 函数。
(2 2 ) 才能在我的应用程序中循环浏览已经打开的视 ? 使用 CDocument 中未公开的 GetFirstViewPosition() 和 GetNextView() 函数。
( 23 ) 数 PreCreateWindow 是干什么用的 ? PreCreateWindow 允许你在调用 CreateWindow 之前来改变窗口属性。
(2 4 ) 该怎样防止 MFC 在窗口标题栏上把文档名预置成应用程序名 ? 在 PreCreateWindow 函数中删除 FWS_PREFIXTITLE 标志的窗口样式: cs.style&=~FWS_PREFIXTITLE;
( 25 ) 我应该怎样防止 MFC 在窗口标题栏上添加文档名 ? 在 PreCreateWindow 函数中删除 FWS_ADDTOTITLE 标志的窗口样式: cs.style&=~FWS_ADDTOTITLE;
(2 6 ) 我应该如何改变视窗口的大小 ? 因为视窗口实际上是框架窗口的子窗口,所以你必须改变框架窗口的大小,而不是改变视窗口。使用 CView 类中的 GetParentFrame() 函数获得指向框架窗口的指针,然后调用 MoveWindow() 函数来改变框架的大小。这会使变尺寸的视充满框架窗口。
( 27 ) 我有一无模式对话框。我怎样才能在窗口退出时删除 CDialog 对象 ? 把 “deletethis” 加到 PostNcDestroy 中。这主要用在需要自动删除对象的场合。
( 28 ) 为什么把 “deletethis” 放在 PostNcDestroy 中而不是 OnNcDestroy? OnNcDestroy 只被已建立的窗口调用。如果建立窗口失败 ( 如 PreCreateWindow) ,则没有窗口处来发送 WM_NCDESTROY 消息。 PostNcDestroy 是在对象窗口被完全删除,在 OnNcDestroy 后,甚至在窗口建立失败之后调用的。
( 29 ) File 菜单中的 MRU 列表是从哪儿来的?列表中的名字放在哪儿了?我怎样才能改变列表中项目的最大值? 在应用程序类的 InitInstance 函数中对 LoadStdProfileSettings 的调用中。该调用接受一个参数 ( 在缺省情况下如果没有传递值则为 4) 。 MRU 文件名是从 INI 文件中调用的。如果你有带有 ID_FILE_MRU_FILE1 的 ID 的菜单选项,它会为调入的 MRU 列表所替换。如果你改变传递给 LoadStdProfileSettings 的数值 ( 最大为 16) ,则你就改变了所装如文件名的最大值。
(3 0 ) 我在菜单中添加了新的项。但是,当我选该项时,在状态栏上没有出现任何提示信息。为什么 ? 打开资源文件中的菜单模板。打开新菜单选项的属性对话框。在对话框的底部的 Prompt 编辑框中,你可以如下指定状态栏上的提示信息和工具栏上的提示信息 ( 如果你已经建立的工具栏按钮 ): Statusbarstring/nFlyingtag
( 31 )我怎样才能在应用程序的缺省系统菜单中加上一些东西 ? 系统菜单与其它菜单类似,你可以添加或删除项目,这需要使用 CMenu 类的成员函数。下面的代码在你的系统菜单后面添加一个新菜单项:
CMenu*sysmenu; sysmenu=m_pMainWnd->GetSystemMenu(FALSE); sysmenu->AppendMenu(MF_STRING,1000,"xxx"); 参见 MFC 帮助文件中的 CMenu 类。
( 32 ) 我建立了一个对话框。但是当我显示该对话框时,第一个编辑框总是不能获得焦点,我必须单击它来使它获得焦点。我怎样才能使第一个编辑框在对话框打开时就获得焦点 ? 打开资源编辑器中的对话框模板。在 Layout 菜单中选择 TabOrder 选项。按你的需求单击对话框中的控制来重新排列这些控制的 tab 顺序。
(3 3 ) 我怎样才能使一个窗口具有 “alwaysontop” 特性 ? 在调用 OnFileNew 后,在你的 InitInstance 函数中加上下面的代码: m_pMainWnd->SetWindowPos(&CWnd::wndTopMost,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE);
(34) 我要为我的 formview 添加文档模板。我先建立了对话框模板,然后使用 ClassWizard 建立了基于 CFormView 的新类,它也是从 CDocument 继承来的。我还建立了相应的资源并在 InitInstance 中添加了新的文档模板。但是,当我试图运行该程序时,出现了 Assertion 信息。为什么 ?
form 的对话框模板需要些特殊设置以便可用于 CFromView 。确保这些设置的最简单方法是使用 AppWizard 来建立 CFormView 应用程序,并查看 AppWizard 所建立的对话框模板所选择的 StylesProperties 。你会发现该对话框模板具有下列样式:没有标题栏、不可见和 “Child” 。把你的 formview 的对话框属性变成这样就可以了。 (35) 我在一对话框中有一列表框,我需要 tabbed 列表框中的项目。但是,当我处理含有 tab 字符 ( 用 AddString 添加的 ) 的列表项时, tab 被显示成小黑块而没有展开。哪儿出错了 ?
在对话框模版中,打开列表框的属性。确保选择了 “UseTabstops” 样式。然后,确保在对话框类中 OnInitDialog 函数中调用 SetTabStops 。 (36) 我建立了一个应用程序,并使用了 CRecordset 类。但是,当我运行该程序时,它试图要访问数据库,并给出 “InternalApplicationError” 对话框。我应该怎样做 ?
通常情况下,当你的程序中向数据库发送信息的 SQL 语句出现问题时才出现该对话框。例如,参见下面的例子: set.m_strFilter="(ZipCode='27111')"; 如果 ZipCode 列被定义为字符串时不会出现问题,如果定义为 long ,则会出现 “InternalApplicationError” 对话框,这是由于类型不匹配的缘故。如果你删除 27111 的单引号,则不会出现问题。当你看到 “InternalApplicationError” 时,最好检查一下试图要发送给数据库的 SQL 语句。 (37) 我用 ClassWizard 建立了一个类。但是,我把名字取错了,我想把它从项目中删除,应该如何做 ?
在 ClassWizard 对话框关闭后,用文件管理器删除新类的 H 和 CPP 文件。然后打开 ClassWizard ,它会提示丢失了两个文件,并询问你该如何做。你可以选择从项目中删除这两个问的按钮。
(38) 当我打开应用程序中的窗口时,我要传递该窗口的矩形尺寸。该矩形指定了窗口的外围大小,但是当我调用 GetClientRect 时,所得到的尺寸要比所希望的值要小 ( 因为工具栏和窗口边框的缘故 ) 。有其它方法来计算窗口的尺寸吗 ?
参见 CWnd::CalcWindowRect 。 (39) 我在文档类中设置了一个整型变量。但是,当我试图把该变量写入 Serialize 函数中的 archive 文件中时,出现了类型错误。而文档中的其它变量没有问题。为什么 ?
archive 类只重载某些类型的 >> 和 << 操作符。 “int” 类型没有在其中,也许是因为 int 变量在 Windows3.1 与 WindowsNT/95 有所不同的缘故吧。 “long” 类型得到了支持,所以你可以把 int 类型改成 long 型。参见 MFC 帮助文件中 CArchive 类。
(40) 如何控制菜单的大小?
我用MFC的CMenu生成了一个动态菜单(例如File,Edit,View...Help), 我想控制这个菜单的大小(长+高).方法一:查找 WM_MEASUREITEM 和 MEASUREITEMSTRUCT.
方法二:查询系统::GetSystemMetric(SM_CXMENUSIZE)./* 你可以通过如下代码来获得文本的大小:
(A)获得被使用的字体 */NONCLIENTMETRICS ncm;
HFONT hFontMenu; SIZE size; size.cy = 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比较合适。*/
(41) 改变LVIS_SELECTED的状态颜色? 我想将CListCtrl项和CTreeCtrl项在LVIS_SELECTED状态时的颜色变灰.方法一:查找函数CustomDraw,它是IE4提供的公共控制,允许有你自己的代码.
方法二:生成一个draw控件,然后在DrawItem中处理文本颜色.
(42) 如何只存储文档的某一部分?
我只想存储文档的某一部分,能否象使用文件一样使用文档?(也就是有定位函数).将每个CArchive类设置为CFile类的派生类,这样你就能使用Seek等成员函数.
(43) 保存工具条菜单有bug吗?
使用浮动菜单条时,SaveBarState和LoadBarState出现了问题.如果菜单是浮动的,重起应用程序时它 会出现在左上角,而它固定在屏幕其它位置时,下一次启动就会出现在该位置,这是什么原因?你试试这个 PToolBar->Create(this,...,ID_MYTOOLBAR);
你的工具条需要包括id,而不是象默认的工具条那样.
(44) 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 != CCommandLineInf:FileDDE ) { CTipDlg dlg; if (dlg.m_bStartup) dlg.DoModal(); } } 如果还有其它bug,你可以设定cmdInfo.m_nShellCommand的过滤.
(45) 如何可以让我的程序可以显示在其它的窗口上面?
让用户选择"总是在最上面"最好是在系统菜单里加入一个选项.可以通过修改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); } } (46) 如何控制窗口框架的最大最小尺寸?要控制一个框架的的最大最小尺寸,你需要做两件事情.在CFrameWnd的继承类中处理消息WM_GETMINMAXINFO,结构MINMAXINFO设置了整个窗口类的限制,因此记住要考虑工具条,卷动条等等的大小.
// 最大最小尺寸的象素点 - 示例 #define MINX 200 #define MINY 300 #define MAXX 300 #define MAXY 400 void CMyFrameWnd::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI) { CRect rectWindow; GetWindowRect(&rectWindow); CRect rectClient; GetClientRect(&rectClient); // get offset of toolbars, scrollbars, etc. int nWidthOffset = rectWindow.Width() - rectClient.Width(); int nHeightOffset = rectWindow.Height() - rectClient.Height(); lpMMI->ptMinTrackSize.x = MINX + nWidthOffset; lpMMI->ptMinTrackSize.y = MINY + nHeightOffset; lpMMI->ptMaxTrackSize.x = MAXX + nWidthOffset; lpMMI->ptMaxTrackSize.y = MAXY + nHeightOffset; } 第二步,在CFrameWnd的继承类的PreCreateWindow函数中去掉WS_MAXIMIZEBOX消息,否则在最大化时你将得不到预料的结果. BOOL CMyFrameWnd::PreCreateWindow(CREATESTRUCT& cs) { cs.style &= ~WS_MAXIMIZEBOX; return CFrameWnd::PreCreateWindow(cs); } (47) 如何改变窗口框架的颜色?MDI框架的客户区被另一个窗口的框架所覆盖.为了改变客户区的背景色,你需要重画这个客户窗口.为了做到这点,你要处理消息WM_ERASEBKND产生一个新类,从CWnd继承,姑且称之为CMDIClient.给它加上一个成员变量,
#include "MDIClient.h" class CMainFrame : public CMDIFrameWnd { ... protected: CMDIClient m_wndMDIClient; } 在CMainFrame中重载CMDIFrameWnd::OnCreateClient BOOL CMainFrame::OnCreateClient(LPCREATESTRUCT lpcs, CCreateContext* pContext) { if ( CMDIFrameWnd::OnCreateClient(lpcs, pContext) ) { m_wndMDIClient.SubclassWindow(m_hWndMDIClient); return TRUE; } else return FALSE; } 然后就可以加入对消息WM_ERASEBKGND的处理了. (48) 如何将应用程序窗口置于屏幕正中?要将你的应用程序窗口放置在屏幕正中央,只须在MainFrame的OnCreate函数中加入:
CenterWindow( GetDesktopWindow() );转载地址:http://eghab.baihongyu.com/