- 第六课
- 菜单的工作原理及编写应用,菜单命令消息在MFC框架程序的几个类中的传递顺序和处理过程。
- 标记菜单、缺省菜单的实现原理、图形菜单的实现及常犯错误的分析,GetSystemMetrics的应用,
- 快捷弹出菜单的实现方式及其命令响应函数有效范围(与弹出菜单时所指定的父窗口有密切的关系,
- 最底层的子窗口具有最优先的处理机会)。动态菜单的编写,如何让程序在运行时产生新的菜单项及
- 如何手工为这些新产生的菜单命令安排处理函数,如何在顶层窗口中截获对菜单命令的处理,
- 更进一步掌握CString类的应用。
- 响应菜单消息,应该在先是view,doc,frame,app
- 消息的分类
- 标准消息
- 除WM_COMMAND之外,所有以WM_开头的消息。
- 从CWnd派生的类,都可以接收到这类消息。
- 命令消息
- 来自菜单、加速键或工具栏按钮的消息。这类消息都以WM_COMMAND呈现。在MFC中,
- 通过菜单项的标识(ID)来区分不同的命令消息;在SDK中,通过消息的wParam参数识别。
- 从CCmdTarget派生的类,都可以接收到这类消息。
- 通告消息
- 由控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是向其
- 父窗口(通常是对话框)通知事件的发生。这类消息也是以WM_COMMAND形式呈现。
- 从CCmdTarget派生的类,都可以接收到这类消息。
- 命令更新
- 菜单项状态的维护是依赖于CN_UPDATE_COMMAND_UI消息,
- 谁捕获CN_UPDATE_COMMAND_UI消息,MFC就在其中创建一个CCmdUI对象。我们可以通过手工
- 或利用ClassWizard在消息映射中添加ON_UPDATE_COMMAND_UI宏来捕获
- CN_UPDATE_COMMAND_UI消息。
- 在后台所做的工作是:操作系统发出WM_INITMENUPOPUP消息,然后由MFC的基类如
- CFrameWnd接管。它创建一个CCmdUI对象,并与第一个菜单项相关联,调用对象的一个成员函数
- DoUpdate()。这个函数发出CN_UPDATE_COMMAND_UI消息,这条消息带有指向CCmdUI对象的
- 指针。同一个CCmdUI对象就设置为与第二个菜单项相关联,这样顺序进行,直到完成所有菜单项。
- 更新命令UI处理程序仅应用于弹出式菜单项上的项目,不能应用于永久显示的顶级菜单项目。
- CRect rect;
- GetClientRect(rect); //得到客户区
- ClientToScreen(rect);
- //定位子菜单在CMainFrame::OnCreate
- GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION|MF_CHECKED);
- GetMenu()->GetSubMenu(0)->CheckMenuItem(ID_FILE_NEW,MF_BYCOMMAND|MF_CHECKED);
- GetMenu()->GetSubMenu(0)->SetDefaultItem(1,TRUE); //设置默认菜单项
- 分割线也是菜单项。
- GetMenu()->GetSubMenu(0)->SetMenuItemBitmaps(); //设置图像标记菜单
- //禁用菜单项
- CMenu::EnableMenuItem
- UINT EnableMenuItem( UINT nIDEnableItem, UINT nEnable );
- 在MFC环境下Menu的修改在默认的情况下是通过CCmdUI来改变的, 调用EnableMenuItem
- 函数无效(不管是全局API还是 CMenu类的成员函数).但是只要修改CFrameWnd类的一个成员
- 变量m_bAutoMenuEnable就可以使调用的函数有效. m_bAutoMenuEnable在默认情况下是TRUE,
- 如果需要EnableMenuItem函数调用有效需将其赋值为FALSE.如下:
- CMainFrm::CMainFrm { // Other stuff m_bAutoMenuEnable=FALSE; //关键部分 }
- SetMenu(NULL); //去除菜单
- CMenu mun;
- mun.LoadMenu(); //加载菜单
- SetMenu(&mun);
- detach()函数: MFC类里CMENU类的成员函数。功能是切断一个CWnd对象和一个有效
- 窗口的联系。 由于WNDCLASS其实和CWnd根本没有什么关系,它们之间只是通过CWnd的
- 成员 HWND联系起来的。Detach的作用是切断一个CWnd对象和一个有效窗口的联系。
- 因为CWnd是C++的对象,C++的对象有一个生存期的概念,脱 离了该对象的作用域,
- 这个对象就要被销毁,但是Windows对象没有这个特点,当销毁CWnd对象的时候,我们不一定
- 希望WNDCLASS一起被销毁, 那么在此之前,我们就先要把这个联系切断。 当我们建立了一个
- 局部的菜单对象后,比如 在一个窗口类的函数里建立了一个局部菜单对象,当这个窗口函数的生命
- 周期结束时,如果不希望菜单对象也被销毁,就要用detach()函数把菜单句柄和这 个菜单对象分离。
- 这样,当局部的菜单对象被销毁时,它不会销毁一个它不具备拥有权的菜单。
- CCmdUI没有基类。 它仅在一个CCmdTarget派生类的ON_UPDATE_COMMAND_UI处理
- 程序中使用。 当用户在应用的下拉菜单时,要确定每个菜单项的显示状态——允许存取或禁止
- 存取。菜单命令的目 标通过实现一个ON_UPDATE_COMMAND_UI处理来提供这些信息。可以使用
- ClassWizard来浏览定位应用中的命令用户接口对象,然后 为它建立一个消息映射入口,并为每个
- 消息处理函数提供函数原型。 当菜单被下拉时,框架搜索并调用每个ON_UPDATE_COMMAND_UI
- 处理,
- 每个处理调用Enable和Check之类的成员函数,相应地,框架就可以正确地显示每个菜单项了。
- void CMainFrame::OnUpdateEditCut(CCmdUI* pCmdUI)
- {
- // TODO: Add your command update UI handler code here
- pCmdUI->Enable(TRUE);
- }
- 创建弹出式菜单
- 在win7下vc++6.0不支持
- components and controls gallery。
- Track pop menu
- void CMyView::OnRButtonUp(UINT nFlags, CPoint point)
- {
- // TODO: Add your message handler code here and/or call default
- CMenu menu;
- menu.LoadMenu(IDR_MENU1);
- CMenu *pPopup=menu.GetSubMenu(0);
- ClientToScreen(&point);
- pPopup->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y,
- GetParent());
- CView::OnRButtonUp(nFlags, point);
- }
- 动态创建菜单在CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)中响应
- CMenu menu;
- menu.CreatePopupMenu(); //创建弹出菜单
- // GetMenu()->AppendMenu(MF_POPUP,(UINT)menu.m_hMenu,"WinSun");//加载菜单
- GetMenu()->InsertMenu(2,MF_BYPOSITION | MF_POPUP,(UINT)menu.m_hMenu,"WinSun"); //插入擦单
- menu.AppendMenu(MF_STRING,IDM_HELLO,"Hello"); //增加菜单项
- menu.AppendMenu(MF_STRING,112,"Weixin");
- menu.AppendMenu(MF_STRING,113,"Mybole");
- menu.Detach();
- GetMenu()->GetSubMenu(0)->AppendMenu(MF_STRING,114,"Welcome");
- GetMenu()->GetSubMenu(0)->InsertMenu(ID_FILE_OPEN,
- MF_BYCOMMAND | MF_STRING,115,"维新");
- GetMenu()->DeleteMenu(1,MF_BYPOSITION);
- GetMenu()->GetSubMenu(0)->DeleteMenu(2,MF_BYPOSITION);*/
- Drawmenubar //重画菜单栏
转载于:https://blog.51cto.com/hantayi/382505