⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 06.3.5 移除和装载菜单.txt

📁 网上第一本以TXT格式的VC++深入详解孙鑫的书.全文全以TXT格式,并每一章节都分了目录,清晰易读
💻 TXT
字号:
6.3.5 移除和装载菜单
在程序中,如果想要移除一个菜单的话,可以利用 CWnd类提供的 SetMenu成员函数来实现,该函数的声明形式如下所示: 
BOOL SetMenu(CMenu* pMenu ); 
这个函数有一个 CMenu类型指针的参数,它指向一个新菜单对象。如果这个参数值为 NULL,则当前菜单就被移除了。于是,为了移除 Menu程序的菜单,可以在上述例 6-10所示 CMainFrame类的 OnCreate函数的最后 Creturn语句前)添加 SetMenu函数调用,结果如例 6-11所示。
例 6-11 

int CMainFrame : :OnCreate(LPCREATESTRUCT lpCreateStruct) 
{ 

GetMenu()->GetSubMenu(O) ->EnableMenultem(l , MF_BYPOS工 T工 ON I MF_DISABLED MF_GRAYED) ; 
SetMenu(NULL); 
return 0 ; 
Build井运行 Menu程序,这时就会发现 Menu程序没有菜单了。程序运行界面如图 
6.22所示。
图 6.22没有菜单的 Menu程序界面

在程序中也可以装载一个菜单资源并显示。例如,在例 6-11中,我们将 Menu程序的菜单移除了,这里,我们可以再把它显示出来。例 6-12就是具体的实现代码,其中加灰显示的部分就是新添的代码。 
iJlJ 6-12 
工 nt CMainFrame ::OnCreate(LPCREATESTRUCT lpCreateStruct) 
GetMenu()->GetSubMenu(O)->EnableMenultem(l , MF_BYPOSITION MF_DISABLED 


182 I ~~~ 


MF_GRAYED) ; SetMenu(NULL) ; 
CMenu menu; menu.LoadMenu(工DR.-MA工NFRAME) ; 
SetMenu(&rnenu) ; 
return 0 ; 
这段新添加的代码首先定义了一个菜单对象: menu,然后与位图对象需要加载位图资源一样,我们也需要把菜单资源加载到这个菜单对象中, Menu程序主菜单的资源标识是 IDR-MADJFRAME。最后调用 SetMenu函数,把程序的菜单设置为刚刚加载的菜单对象。 
Build并运行Menu程序,会发现这时Menu程序的菜单又出现了。
飞令·姐iRfii在编程中,除了使用MFC自动创建的IDRMAINFRAME菜单以外,还

可以自已创建一个菜单资源并加载,然后调用 SetMenu函数,从而使程序的菜单变成自

己定义的这个菜单。通过这种方式,可以实现动态更换程序某单的功能。 
r一阳l对于上述例6-12所示的代码,不知读者是否注意到 
001啕a…"'...副一个问题,这里定义的CMenu对象: menu是一个局部
份喃嗣
同缸,.,,,..... 

-.… 对象,但程序似乎并未出现异常(笔者的程序运行在 
For iloi 11细,......... ycu 111...,_~ca翩翩…筒"

,....…·蝇..C++dc跑"‘a圃,CIfI tI. Windows 2000系统下,如果是WindowsNtr则会出现
栖-民由V幅"缸啕…d幅幅。
回!!U. -.m I 异常〉。实际上,这段代码仍然是有问题的。在Windows 

2000系统下,进行下列操作,将会出现错误:运行Menu
图 6刀程序异常信息对话框程序,首先选择【文件】子菜单下的【打印预览】菜单项,这时会出现打印预览窗口,关闭打印预览窗口,将会发现这时Menu程序的菜单没有了。接着再关闭这个Menu程序。程序就会出现非法操作,显示如图6.23所示的异常信息对话框。这个异常的产生是因为这里的CMenu对象: menu是一个局部对象造成的。
为了解决这个问题,可以把上述例6-12所示代码中的CMenu对象定义为CMainFrame类的一个成员变量。这里,再介绍另一种解决方式。仍把这个菜单对象定义为局部对象,但在调用 SetMenu函数把此对象设置为窗口的菜单之后,立即调用 CMenu类的另一个成员函数Detach,以便把菜单句柄与这个菜单对象分离。 SetMenu函数会把窗口的菜单设置为其参数指定的新菜单,导致窗口重绘,以反映菜单的这种变化,同时也将该菜单对象的所有权交由给窗口对象。而随后的Detach函数会把菜单句柄与这个菜单对象分离,这样,
当这个局部菜单对象的生命周期结束时,它不会去销毁-个它不再具有拥有权的菜单。这个菜单在窗口销毁时会自动销毁。因此,我们在上述例6-12所示代码的最后,再添加对菜单对象的Detach函数的调用,代码如例6-13所示。 
0tl6-13 

工nt CMainFrame : :OnCreate(LPCREATESTRUCT lpCreateStruct) 

{ 
" ‘ I 183 


GetMenu()->GetSubMenu(Q)->Enabl eMenultem(l , Tσ、一BYPOSITION MF_DISABLED MF_GRAYED) ; SetMenu (NULL) ; 
CMenu menu; 
menu.LoadMenu(IDR_MAINFRAME) ; 
SetMenu (&menu) ; 
menu.Detach(); 

return Q; 
. 
Build并运行Menu程序,再重复上次导致程序出现非法操作的步骤,打开【文件】子
菜单下的【打印】预览菜单项,并把出现的打印预览窗口关闭,再关闭这个Menu程序,
这时会发现程序一切正常,没有出现刚才的非法操作。
国际:在设置窗口菜单时,如果定义的是局部菜单对象,则一定要在调用 
SetMenu函数设直窗口菜单之后,立即调用菜单对象的Detach函数将菜单句柄
与菜单对象分离。 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -