设为首页 加入收藏

TOP

5.2.3 同菜单有关的类
2013-10-06 23:58:29 来源: 作者: 【 】 浏览:57
Tags:5.2.3 菜单 有关

5.2.3  同菜单有关的类
MFC提供了菜单类CMenu。在应用程序中,可通过CMenu类的成员函数对菜单进行控制。利用这些函数,我们可以很方便地进行菜单的动态修改,包括添加/删除菜单项、修改菜单项文字内容或制作图形菜单。这些成员函数主要有:
(1)AppendMenu()
该函数用于在指定的菜单项最后附加一个新的菜单项,可以同时指定菜单状态以及标记情形。其函数原型如下:

BOOL AppendMenu( UINT nFlags, UINT nIDNewItem = 0, LPCTSTR lpszNewItem = NULL );

BOOL AppendMenu( UINT nFlags, UINT nIDNewItem, const CBitmap* pBmp );


返回值:若函数成功,则返回非0值;否则返回0。
参数nFlags用于指定加入到菜单中的新菜单项状态的信息,应用程序可以通过设置nFlags的值来确定菜单状态。当nIDNewItem确定了一个弹出式菜单时,它就被确认为是被扩展菜单的一部分。当菜单被破坏时,其扩展部分也将被破坏,一个扩展菜单同样可以从一个CMenu对象中获取以避免冲突。值得注意的是,值MF_STRING和MF_OWNER_DRAW对于位图版本的AppendMenu()是无效的。
为nFlags设置的标志如下:
MF_CHECKED:作为一个MF_UNCHECKED的开关,放置一个缺省的选中标志到选项后面。当应用程序提供选中标志位图时,“选中标志打开”的点位图将被显示。
MF_UNCHECKED:作为MF_CHECKED的开关,去掉选项后的选中状态。当应用程序提供了选中标志的位图时,“选中标志关闭”点位图将被显示。
MF_DISABLED:使菜单项禁止,使它不能被选择但不把它变灰。
MF_ENABLED:使菜单项能被选择,并把它从变灰状态恢复到正常状态。
MF_GRAYED:使菜单项禁选,并使之变灰。
MF_MENUBARBREAK:在静态菜单中把选项放在新的行中或把弹出菜单放于新栏中,新的弹出式菜单栏将与老的用竖线分开。
MF_MENUBREAK:将一菜单项放于静态菜单的新一行中或弹出菜单的新栏中,新旧菜单不用分割线分开。
MF_OWNERDRAW:确认选项是否为自绘制风格。当菜单为头一次显示时,拥有菜单的窗口返回一条WM_MEASUREITEM消息,它返回菜单项的高度和宽度,WM_DRAWITEM消息是在拥有窗口改变菜单选择的外观时发送的,它对顶层菜单选项无效。
MF_POPUP:确认一个选项是否有弹出式菜单与之相关。ID参数可以确认一个与此选项相关的弹出菜单的句柄,它可用来为一个顶层菜单或弹出菜单的一个选项添加一个相关的弹出式菜单。
MF_SEPARATOR:绘制一条垂直分界线,仅用于弹出式菜单,此线可以变灰、禁止或点亮,其他参数将忽略。
MF_STRING:确定菜单选项是一个字串。
下列选择组间的各项是互斥的,不能一起使用:
MF_DISABLED,MF_ENABLED和MF_GRAYED。
MF_STRING,MF_OWNERDRAW,MF_SEPARATOR和点位图版本。
MF_MENUBARBREAK和MF_MENUBREAK。
MF_CHECKED和MF_UNCHECKED。
无论何时,只要窗口中的菜单被改变,应用程序都会调用CWnd::DrawMenuBar。
该函数在调用成功时返回非0,否则返回0。
参数lpszNewItem用于指定新菜单项的内容。
参数pBmp用于指向一个将用作新菜单项的CBitmap对象。
(2)InsertMenu()
该函数用于在指定菜单项之前插入新菜单项,其函数原型如下:
BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCTSTR 
lpszNewItem = NULL );

BOOL InsertMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem, const CBitmap*
pBmp );


返回值:若成功,返回非0;否则返回0。
参数nPosition用于指定要插入的新菜单项的前面一项。参数nFlags用于指定对nPosition如何解释,并指定新菜单项在加入到菜单中时的状态信息。参数nIDNewItem用于指定新菜单项的命令ID。参数lpszNewItem用于指定新菜单项的内容。参数pBmp用于指向一个CBitmap对象,该对象将用做菜单项。
该函数用于向一个菜单中nPosition指定的位置插入一个菜单项,并把其他项向后移,其应用程序可以用对nFlags赋值的办法设置此菜单项的状态。只要窗口中的菜单发生变化(无论窗口是否显示),都要调用CWnd::DrawMenuBar。nIDNewItem用于确定一个弹出菜单。在它插入菜单时,它会变为菜单的一部分。若菜单被破坏,它也随之被破坏。插入菜单项应从一个CMenu对象中获取,以免发生重复。
如果活动多文档窗口的子窗口变为最大,则应用程序调用此函数在子窗口菜单中插入一个弹出式菜单,并设置MF_BYPOSITION标志。菜单将插入到所预期位置的左边。因为活动MDI子窗口的控制菜单将被插入到MDI框架窗口菜单条的第一个位置。为使位置正确,应用程序必须对位置变量加1。一个应用程序可以用WM_MDIGETACTIVE消息确认当前活动子窗口是否最大。
(3)ModifyMenu()
该函数可以修改现有的菜单项,包括菜单标题、菜单项状态和菜单项ID值。其原型如下:

BOOL ModifyMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem = 0, LPCTSTR 
lpszNewItem = NULL );

BOOL ModifyMenu( UINT nPosition, UINT nFlags, UINT nIDNewItem, const CBitmap*
pBmp );


其参数意义同InsertMenu函数是一样的。
函数改变由nPosition确定的已存在的菜单项。应用程序可以用nFlags值来确定选项的新状态。若此菜单改变了与此菜单相联的弹出菜单,它将破坏老的弹出式菜单并释放由此菜单占用的内存。当nIDNewItem确定的弹出式菜单变成插入的菜单的一部分时,若菜单被破坏,则插入菜单也将被破坏。插入菜单应从CMenu对象中获得,以避免冲突。
只要驻留于窗口的菜单被改变(无论窗口是否显示),应用程序都将调用DrawMenuBar()函数。
当该函数被用来改变一个已存在的选项状态的属性时,它比使用CheckMenuItem()和EnableMenuItem()成员函数快得多。
该函数调用成功时,返回非0,否则为0。
(4)RemoveMenu()
RemoveMenu()函数的原型如下:

BOOL RemoveMenu( UINT nPosition, UINT nFlags );

该函数用于删除一个弹出式菜单的菜单选项,但它不破坏一个弹出菜单的句柄,菜单仍可以被使用。在调用此函数之前,应用程序可以调用GetSubMenu()成员函数获取弹出的CMenu对象以便重新使用。只要位于窗口内的菜单被改变(无论窗口是否显示),应用程序就必须调用DrawMenuBar()函数。
该函数在成功时返回非0,否则为0。
(5)DeleteMenu()
该成员函数用于删除不用的菜单项,其原型如下:

BOOL DeleteMenu( UINT nPosition, UINT nFlags );

参数nPosition用于指定要插入的新菜单项的前面一项。参数nFlags用于指定对nPosition如何解释,并指定新菜单项在加入到菜单中时的状态信息。
该函数用于从菜单中删除一项,若菜单项有一隶属弹出菜单,DeleteMenu()破坏弹出菜单,师范由此弹出菜单占用的内存。当一个窗口中有菜单变化(无论窗口是否显示),应用程序会调用DrawMenuBar()函数。
该函数成功调用时返回非0,否则为0。
(6)TrackPopupMenu()
该函数比较特殊,它用于控制右键激活的动态菜单的设置和显示。它的原型如下:

BOOL TrackPopupMenu( UINT nFlags, int x, int y, CWnd* pWnd, LPCRECT lpRect = NULL );

其中,参数pWnd用于指定动态菜单的所属窗口;lpRect用于指定鼠标的有效范围,如果为NULL,则鼠标必须在动态菜单内操作才有效。
此外,在CWnd类中有几个与菜单功能相关的重要函数。
(7)SetMenu()
该函数用来删除或替换现有菜单,其参数为一个菜单对象的指针,若为NULL则删除现有菜单。
(8)GetMenu()
该函数用来获取一个菜单对象的指针,其参数为该菜单的ID标识符号。
(9)GetSysMenu()
该函数用来获取系统菜单的一个指针,这个函数不需要参数。
说明:一般的Windows程序都有一个系统菜单,这个菜单由系统生成,并由系统管理,主要有“移动”,“大小”,“最小化”,“最大化”,“关闭”等用户可以在任何一个程序的窗口标题栏上右击,就会看到弹出的系统菜单,如图5-8所示。

【实例5-1】  菜单实例
光盘路径   /05/ test1/
实例目的   创建菜单
1.创建工程
启动Microsoft Visual Studio 6.0,在IDE中依次选择“File”→“New”菜单命令,或直接按快捷键“Ctrl+N”,打开“New”对话框。
在“New”对话框中单击“Projects”选项卡,在列表框中选择“MFC AppWizard(.exe)”项,在“Project name”文本框中输入“test1”,其他使用默认值,单击“OK”按钮,弹出“MFC AppWizard-Step1”对话框。
在“MFC AppWizard-Step1”对话框中,选中“Multiple Document”单选框,其他使用默认值,然后单击“Finish”按钮,在弹出的“New Project Information”对话框中单击“OK”按钮,就可以完成工程的创建。
创建工程后,可以发现自动生成的应用程序框架中包含了默认的菜单,根据用户在创建时的不同选项,默认菜单中的菜单项有所不同。对于SDI应用程序,只生成一个菜单,其资源ID为IDR_MAINFRAME(资源ID用于标识资源,程序装入资源需要指定该ID来确定需要装入哪个资源),这是整个应用程序共用的菜单。对于MDI应用程序,要生成两个菜单,其资源ID分别为IDR_MAINFRAME和IDR_工程名TYPE,当应用程序尚未打开文档时显示第一个菜单,打开文档后显示第二个菜单。
2.添加菜单资源
添加资源ID为IDR_TEST1TYPE的菜单,该菜单标题为“周星驰”,其有两个子菜单,分别为“苏乞儿”和“大话西游”,其步骤如下。
在工作区中选择的Resource View标签,转到资源编辑窗口,双击“Menu”→ “IDR_MAINFRAME”条目打开该菜单资源的编辑界面,如图5-9所示。

 
图5-9  菜单资源的编辑界面

双击“帮助”菜单项右侧的虚线框,弹出新建顶层菜单项的属性编辑对话框,如图5-10所示。注意,这个虚线框可以用鼠标拖动到顶层菜单的任何位置。在“Caption”文本框中输入菜单项的标题“周星驰(&D)”。标题中“&D”的作用是在程序运行时用户可以按“Alt+D”组合键直接打开菜单项,在显示时,“&D”会转换为添加了下划线的“D”,如图5-10所示。“Pop_up”复选框默认被选中,表明这是一个弹出菜单项,允许有子菜单。

 
图5-10  添加“周星驰”菜单项

关闭如图5-10所示的对话框,单击资源编辑器中的“周星驰”的菜单项,会显示它的下层菜单,如图5-11所示。因为没有添加任何子菜单项,所以“周星驰”的下层菜单是空的,显示为一个虚线框。在图5-11中单击这个虚线框,弹出类似于图5-10的属性编辑对话框,如图5-12所示。

其中,在“ID”文本框中输入“ID_MOVOE1”,“Caption”文本框中输入“苏乞儿(&Y)”,“Prompt”文本框中输入“打开电影《周星驰—苏乞儿》”。标题中的“&Y”表示打开“周星驰”菜单项后,在键盘上按“Y”键就可以直接选择“苏乞儿”菜单项。当鼠标光标移动到“苏乞儿”这个菜单项上时,会在程序的状态栏中显示“Prompt”文本框的内容,即“打开电影《周星驰—苏乞儿》”。回车关闭属性编辑对话框,保存修改。
按照步骤 的方法加入“大话西游”菜单项,在“ID”文本框中输入“ID_MOVOE2”,“Caption”文本框中输入“大话西游(&X)”,“Prompt”文本框中输入“打开电影《周星驰—大话西游》”,其属性对话框如图5-13所示。


图5-13  添加“大话西游”菜单项

3.添加菜单的处理函数
创建好菜单后,我们来运行一下看看,就会发现“周星驰”下的两个菜单项是灰色的,也就是说是禁用的。如图5-14所示。

 
图5-14  添加菜单项

这是因为菜单缺少相应的用户处理函数,主框架类禁用了这两个菜单项,因此还需要为菜单消息添加消息处理函数。其过程如下。
在IDE主菜单栏中单击“View”→“ClassWizard”,或者直接使用快捷键“Ctrl+W”来打开“MFC ClassWizard”对话框,单击“Message Maps”选项卡。
添加“苏乞儿”菜单项的消息处理函数。在“Project”下拉列表框中选择“test1”在“Class name”下拉列表框中选择需要编辑的类,这里选“CTest1View”,在“Object IDs”列表框中选择需要添加处理函数的命令消息“ID_MOVOE1”,在“Messages”列表框中选择“COMMAND”,然后单击“Add Function”按钮,弹出添加的函数名对话框,如图5-15所示。


图5-15  添加函数名对话框

为ID_MOVOE1添加命令消息处理函数,在弹出的对话框中保持其默认值,直接单击“OK”按钮,返回ClassWizard对话框。可以看见在“Member function”列表中已经添加了一个名为OnMovoel的新函数。
按照步骤   中的方法,为“大话西游”菜单项添加消息处理函数OnMovoe2(),添加后的ClassWizard对话框如图5-16所示。


图5-16  添加了两个消息处理函数后的ClassWizard对话框

4.添加代码
“Member function”列表选择函数OnMovoel,单击“Edit Code”按钮退出“ClassWizard”对话框,并自动打开MainFrm.cpp文件,且定位在OnMovoel ()函数上。在这里添加如下代码:

void CMainFrame::OnMovoe1() 
{
// TODO: Add your command handler code here
MessageBox("苏乞儿这部影片大悲大喜的故事框架更适合确立一种正剧的风格。","苏乞儿");
}

在MainFrm.cpp文件中找到CMainFrame::OnMovoe2()函数,为其添加如下代码:

void CMainFrame::OnMovoe2() 
{
// TODO: Add your command handler code here
MessageBox("大话西游由月光宝盒和大圣娶亲两部组成,讲述了一个跨越时空的爱情故事...","
大话西游");
}

5.编辑并运行程序
编辑、链接并运行程序,关闭所有文档。依次选择“周星驰”→“苏乞儿”可以看到如图5-17所示的运行结果。


图5-17  菜单应用程序运行结果

同样的单击“周星驰大话西游”菜单项,也能看到与图5-17类似的运行结果,如图5-18所示。


图5-18  大话西游菜单项

【责任编辑:杨硕 TEL:(010)68476636-8001】

回书目   上一节   下一节

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇4.2.1 WM_LBUTTONDOWN 下一篇5.2 菜单、加速键和串表

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: