1.顶层菜单如File等一般为弹出式菜单,popup属性为TRUE,而以下的菜单命令的popup属性一般为FALSE。
2.可以在资源管理器创立新的菜单,而后在Mainframe.cpp里改写OnCreate函数,示例代码如下:
CMenu menu;
menu.LoadMenu(IDR_MENU1);
this->SetMenu(&menu);
其中IDR_MENU1为你新建立的菜单的ID号,这段代码可以覆盖创建MFC时默认的菜单。
3.给菜单添加COMMAND消息处理
这里有两种消息类型:COMMAND和UPDATE_COMMAND_UI,其中UPDATE_COMMAND_UI消息是当菜单需要重绘时由系统发送的。例如,弹出一个个的菜单命令时,每弹出一个则发出一个UPDATE_COMMAND消息,你可以响应这个消息,做一些处理,例如打钩、打点、变灰等。注意:UPDATE_COMMAND_UI只能由拥有菜单的窗口发出!
4.给菜单添加UPDATE_COMMAND_UI消息处理程序
示例代码如下:
void CMainFrame::OnUpdateColorBlue(CCmdUI *pCmdUI)
{
// TODO: 在此添加命令更新用户界面处理程序代码
pCmdUI->SetCheck(TRUE);
}
上述代码的效果是在弹出Blue命令时,在前面打钩。
5.菜单快捷键和加速键
快捷键:菜单前加&,加速键(\t后加热键),可以在不打开菜单的情况下直接执行菜单命令。
6.标记菜单
在菜单命令前有一个对勾的菜单称为标记菜单,我们可以在CMainFrame的OnCreate函数中添加代码来实现这个功能。
首先必须获得这个菜单命令,然后才能进行操作,看几个关键函数:
CMenu* GetMenu()const //返回菜单指针,入无菜单返回NULL;
CMenu* GetSystemMenu(BOOL bRvert) const; //返回系统菜单指针,bRvert为FALSE科修改菜单,TRUE则恢复默认菜单
CMenu* GetSubMenu(int nPos)const; // 返回子菜单指针
UINT CheckMenuItem(UINT nIDCheckItem, UINT nCheck); //第一个参数为需要处理的菜单命令,第二个为处理方法(MF_CHECKED,MF_UNCKECKED,MF_BYPOSITION)。
实现标记菜单的代码如下:
GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION|MF_CHECKED);
7.菜单加入图标
关键函数:SetMenuItemBitmaps(UINT nPosion, UINT nFlags, const CBitmap* pBmpUnchecked, const CBitmap* pBmpChecked);
首先要把位图放到资源文件里,然后再加载显示,注意的问题是位图的尺寸,若太大的话往往只会显示一部分。
8.禁用菜单
利用EnableMenuItem(UINT nIDnableItem, UINT nEnable)来设置菜单状态:启用、禁用或者变灰。例程如下:
GetMenu()->GetSubMenu(0)->EnableMenuItem(1,MF_BYPOSITION|MF_DISABLE|MF_GRAYED);
通过这句代码,我们可以禁用第一个菜单项的第二个菜单命令。 注意:必须先在CMainFrame的构造函数中把m_bAutoMenuEnable设置为FALSE,这是因为在MFC中默认生成的菜单命令由内部维护,用户改写的话必须把这个变量设置为FALSE。
如果我们想要程序根据某些条件选择性的启动和禁用菜单命令,就可以选择UPDATE_COMMAND_UI。
9.移除和加载菜单
SetMenu(NULL)可以移除菜单;SetMenu(&menu)可以加载菜单。
注意:如果定义一个局部的CMenu对象,然后调用SetMenu函数,会产生异常,一种处理方法是在实现方法的类中南添加CMenu成员,另一种方法是在调用完SetMenu函数后,调用menu。Detach()。
10.菜单消息
文档类和应用程序类派生自CCmdTargetl类,不能接收标准消息,消息执行顺序是:视图类->文档里->框架类->应用程序类。
11.动态菜单
方法:定义一个CMenu的对象menu,利用CreatePopupMenu初始化menu对象,利用AppendMenu函数添加动态菜单,以下是示例代码:
CMenu menu;
menu.CreatePopupMenu();
GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu, _T("星期"));
menu.AppendMenu(MF_STRING, 111, _T("星期六"));
menu.AppendMenu(MF_STRING, 112, _T("星期日"));
其中,111和112是菜单命令的ID号,(UINT)menu.m_hMenu是弹出式菜单的句柄值。
同样,也可以在已有菜单之间插入菜单,利用InsertMenu函数。
RemoveMenu函数移除一个菜单,但保留菜单的句柄,空间也不释放;DeleteMenu函数删除一个弹出式菜单时也同时销毁了这个菜单的句柄,释放了空间:示例代码如下:
GetMenu()->DeleteMenu(1,MF_BYPOSITION); //删除第2个菜单(如“编辑”)。
GetMenu()->GetSubMenu(0)->DeleteMenu(2,MF_BYPOSITION); // 可以删除菜单命令
12.如何为动态菜单添加响应
(1)添加菜单ID; (2)添加消息函数声明; (3)ON_COMMAND(IDM_XXX, ONXXX); (4) 实现消息处理函数。