本主要介绍菜单的基本使用,在MFC中用于指定菜单项位置有两种方式,它们是MF_BYCOMMAND和MF_BYPOSITION,在菜单操作中经常用到,具体含义如下:
如图1是一个MFC窗口,其中文件、编辑、视图所在的位置是菜单栏,其中“文件(F)”、“编辑(E)”都是子菜单,“新建(N)”,“保存(S)”等是菜单项。菜单项可以通过菜单项的标识ID进行访问,而子菜单只能通过索引号进行访问。
图1MFC窗口
voidDrawMenuBar();
CMenu*GetMenu()const;
CMenu*GetSystemMenu(BOOLbRevert)const;
BOOLHiliteMenuItem(CMenu*pMenu,UINTnIDHiliteItem,UINTnHilite);
BOOLSetMenu(CMenu*pMenu);
CMenu*GetSubMenu(intnPos)const;由于程序的主菜单属于框架窗口,所以需要在框架窗口创建完成之后,再去访问菜单对象,我们可以在框架类的OnCreate函数return之前添加相应的代码,如果在CMainFrame类中没有OnCreate响应函数,需要我们手动添加该函数。
在视图子菜单下面有“工具栏(T)”和"状态栏(S)"两个菜单项,在它们前面都有一个对号(√),我们称这种类型的菜单为“标记菜单”,如图2所示。
图2标记菜单
UINTCheckMenuItem(UINTnIDCheckItem,UINTnCheck);现在我们将“文件(F)”下的“打开(O)”菜单项设置为标记菜单,实现代码如下:
intCMainFrame::OnCreate(LPCREATESTRUCTlpCreateStruct){...//标记菜单GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_OPEN,MF_BYCOMMAND|MF_CHECKED);return0;}运行效果:
BOOLSetDefaultItem(UINTuItem,BOOLfByPos=FALSE);实现代码如下:
intCMainFrame::OnCreate(LPCREATESTRUCTlpCreateStruct){...//默认菜单GetMenu()->GetSubMenu(0)->SetDefaultItem(ID_FILE_NEW,FALSE);return0;}
运行效果:
BOOLSetMenuItemBitmaps(UINTnPosition,UINTnFlags,constCBitmap*pBmpUnchecked,constCBitmap*pBmpChecked);在图形标记菜单中,显示的位图尺寸有固定的大小,其高度和宽度都是13*13。
代码实现如下:
intCMainFrame::OnCreate(LPCREATESTRUCTlpCreateStruct){...//图形标记菜单m_BmpItem.LoadBitmap(IDB_BITMAP1);GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(2,MF_BYPOSITION,&m_BmpItem,&m_BmpItem);return0;}运行效果:
为了达到屏蔽某些菜单功能,我们可以使用EnableMenuItem函数来实现,该函数的功能是设置菜单状态:能够使用、禁用或变灰显示,其函数如下:
UINTEnableMenuItem(UINTnIDEnableItem,UINTnEnable);为了将EnalbeMenuItem函数正常生效,需要在MainFrame构造函数中将m_bAutoEnableMenus设置为False,此时MFC菜单项的显示状态不会自动更新,需要我们自己维护菜单显示状态。
我们将m_bAutoEnableMenu设置为False后,那些没有设置功能的菜单项也都会显示为非灰色,造成误解,为了将某些功能禁用需要调用EnableMenuItem函数,具体代码:
intCMainFrame::OnCreate(LPCREATESTRUCTlpCreateStruct){...//禁用编辑下的所有菜单项功能CMenu*SubEditMenu=GetMenu()->GetSubMenu(1);SubEditMenu->EnableMenuItem(0,MF_BYPOSITION|MF_DISABLED|MF_GRAYED);SubEditMenu->EnableMenuItem(2,MF_BYPOSITION|MF_DISABLED|MF_GRAYED);SubEditMenu->EnableMenuItem(3,MF_BYPOSITION|MF_DISABLED|MF_GRAYED);SubEditMenu->EnableMenuItem(4,MF_BYPOSITION|MF_DISABLED|MF_GRAYED);return0;}运行效果:
在程序中,如果希望移除一个菜单的话或同时加载一个新的菜单可以利用Cwnd类提供的setMenu函数来实现。移除和装载一个菜单代码实现如下:
intCMainFrame::OnCreate(LPCREATESTRUCTlpCreateStruct){...//默认的菜单栏从窗口中移除SetMenu(NULL);//设置新的菜单栏CMenumenu;menu.LoadMenu(IDR_MENU_TEST);//自定义的菜单栏//将自定义菜单栏绑定到窗口SetMenu(&menu);//将menu对象中的m_hMenu和菜单栏资源分离,//避免menu对象析构时,菜单栏资源也被析构menu.Detach();/*HMENUCMenu::Detach(){HMENUh=m_hMenu;m_hMenu=NULL;returnh;}*/return0;}运行效果:
BOOLTrackPopupMenu(UINTnFlags,intx,inty,CWnd*pWnd,LPCRECTlpRect=NULL);
具体代码如下:
voidCCMenuView::OnContextMenu(CWnd*/*pWnd*/,CPointpoint){//TODO:在此处添加消息处理程序代码CMenumenu;VERIFY(menu.LoadMenu(IDR_MENU_RBUTTON));CMenu*pPopup=menu.GetSubMenu(0);pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);}
方式二:
voidCCMenuView::OnRButtonDown(UINTnFlags,CPointpoint){//TODO:在此添加消息处理程序代码和/或调用默认值//该消息响应函数需要将转换鼠标点击坐标ClientToScreen(&point);CMenumenu;VERIFY(menu.LoadMenu(IDR_MENU_RBUTTON));CMenu*pPopup=menu.GetSubMenu(0);pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON,point.x,point.y,this);CView::OnRButtonDown(nFlags,point);}