参考《VC++深入详解》孙鑫
管理者
菜单由CMenu类管理,CMenu类派生于CObject类。
使用方式
在局部堆栈或全局堆中创建CMenu对象调用CMenu类的成员函数对其进行操作调用CWnd::SetMenu将菜单挂接到某个窗口——此函数将新菜单作为窗口菜单,并立即重新对其进行绘制立即调用CMenu::Detach函数——此函数解除HEMENU与CMenu对象之间的联系
COMMAND与UPDATE_COMMAND_UI消息的区别响应菜单项命令的顺序
视类->文档类->框架类->应用程序类
windows消息分类
标准消息除
WM_COMMAND之外,所有以WM_开头的消息都是标准消息。从CWnd派生的类,都可以接收到这类消息。命令消息来自菜单、加速键或工具栏按钮的消息。这类消息都以
WM_COMMAND形式呈现;在MFC中,通过菜单项的ID来区分不同的命令消息;在SDK中,通过消息的wParam参数识别。从CCmdTarget派生的类,都可以接收到这类消息。通告消息由控件产生的消息,例如按钮的单击、列表框的选择等都会产生这类消息,目的是为了向其父窗口(通常是对话框)通知事件的发生。这类消息也是以
WM_COMMAND形式呈现的;
操作函数
基本菜单操作: GetMenu->GetSubMenu(0);标记菜单: GetMenu->GetSubMenu(0)->CheckMenuItem(0, MF_BYPOSITION|MF_CHECKED);默认菜单项: GetMenu->GetSubMenu(0)->SetDefaultItem(1,TRUE);图形标记菜单: SetMenuItemBitmaps()
第三个参数pBmpUnchecked: 取消菜单项选中状态时的位图第四个参数pBmpChecked: 选中菜单项时显示的位图GetSystemMetric函数:可以获得图形标记菜单上显示的位图的尺寸禁用菜单项: EnableMenuItem函数(如果想自己更改菜单项的状态,必须先把m_bAutoMenuEnable变量设置为FALSE,之后自己对菜单项状态的更新才起作用)移除和装载菜单
移除: SetMenu(NULL);装载:
CMenu menu;menu.LoadMenu(IDR_MAINFRAME);SetMenu(&menu);menu.Detach();加载菜单后因为菜单是局部对象出现问题的解决方案
把menu定义为CMainFrame的成员变量调用SetMenu函数把此对象设置为窗口的菜单之后,立即调用CMenu类的另一个成员函数Detach,以便把菜单句柄与这个菜单对象分离说明:Detach函数会把菜单句柄与这个菜单对象分离,这样当这个局部对象声明周期结束时,它不会去销毁一个它不再拥有的菜单,这个菜单在窗口销毁时会自动销毁。MFC菜单命令更新机制
当要显示菜单时,操作系统发出WM_INITMENUPOPUP消息,然后由程序窗口的基类如CFrameWnd接管;它会创建一个CCmdUI对象,并与程序的第一个菜单项相关联,调用该对象的一个成员函数DoUpdate(),这个函数发出CN_UPDATE_COMMAND_UI消息,这条消息带有一个指向CCmdUI对象的指针;这时,系统会判断是否存在一个ON_UPDATE_COMMAND_UI宏去捕捉这个菜单项消息,如果找到这样一个宏,就调用相应的消息响应函数进行处理,在这个函数中,可以利用传递过来的CCmdUI对象去调用相应的函数,使该菜单项可以使用或禁用该菜单项;当更新完第一个菜单项后,同一个CCmdUI对象就设置为第二个菜单项相关联,依次顺序进行,直到完成所有菜单项的处理。
快捷菜单
添加步骤:
做一个菜单资源添加右键消息(WM_RBUTTONDOWN)响应函数在响应函数中添加代码
加载菜单
CMenu menu;menu.LoadMenu(IDR_XXX);CMenu *pMenu = menu.GetSubMenu(1);显示菜单
ClientToScreen(&point);pMenu->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON, point.x,point.y,GetParent());
动态菜单操作
包括针对弹出菜单的动态操作和针对菜单项的动态操作。
添加菜单项目
AppendMenu例子
CMenu menu;menu.CreateMenu();GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu,"test");menu.Detach();插入菜单项目
InsertMenu在两个子菜单之间插入一个子菜单在两个菜单项之间插入一个新的菜单项 例子
CMenu menu;menu.CreateMenu();GetMenu()->InsertMenu(2,MF_POPUP|MF_BYPOSITION,(UINT)menu.m_hMenu,"Test"); //子菜单GetMenu()->GetSubMenu(0)->InsertMenu(ID_FILE_OPEN,MF_BYCOMMAND|MF_STRING,115,"VC 编程"); //菜单项menu.Detach();删除菜单
BOOL DeleteMenu(UINT nPosition, UINT nFlags);例子
GetMenu()->DeleteMenu(1,MF_BYPOSITION);GetMenu()->GetSubMenu(0)->DetletMenu(2,MF_BYPOSITION);动态添加菜单项的命令响应
方法:通过编辑resource.h,在其中添加动态菜单项的资源ID,然后为此资源添加相应的消息处理机制。具体做法:
#define IDM_HELLO 111添加函数中修改为:menu.AppendMenu(MF_STRING,IDM_HELLO,"hello");添加消息映射及响应函数
afx_msg void OnHello();ON_COMMAND(IDM_HELLO,OnHello) //无分号void CMainFrame::OnHello() {...}
转载于:https://www.cnblogs.com/huan7550/archive/2013/03/21/2973108.html