📄 06.3.5 移除和装载菜单.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 + -