MFC学习笔记之四————菜单编程与windows消息分类

来源:互联网 发布:什么样买卖数据犯法 编辑:程序博客网 时间:2024/05/17 03:30

      首先,在MFC中,具有PopUp属性的菜单是不能用来做命令响应的。

在MFC中:

                  当点击一个菜单项的时候,最先接受到菜单项消息的是CMainFrame框架类,CMainFrame框架类将会把菜单项消息交给它的子窗口View类,由View类首先进行处理;如果View类检测到没对该菜单项消息做响应,则View类把菜单项消息交由文档类Doc类进行处理;如果Doc类检测到Doc类中也没对该菜单项消息做响应,则Doc类又把该菜单项消息交还给View类,由View类再交还给CMainFrame类处理。如果CMainFrame类查看到CMainFrame类中也没对该消息做响应,则最终交给App类进行处理。

所以,其消息传递顺序为:View类--Doc类--CMainFrame类--App类。当然,菜单消息一旦在其中一个类中响应则不再在其它类中查找响应函数

               windows消息的分类

(1)标准消息:除WM_COMMAND之外,所有以WM_开头的消息。从CWnd类派生的都可以接收到这些消息。

(2)命令消息:来自菜单、加速键或工具栏按钮的消息。这类消息都以WM_COMMAND呈现。在MFC中,通过菜单项的标识(ID)来区分不同的命令消息;在SDK中,通过消息的wParam参数识别。

(3)通告消息:由控件产生的消息,例如,按钮的单击,列表框的选择等均产生此类消息,为的是向其父窗口(通常是对话框)通知事件的发生。这类消息也是以                    WM_COMMAND形式呈现。——————从CCmdTarget派生的类,都可以接收到[命令消息]和[通告消息]


在menu操作过程中,几个函数需要了解:

CMenu* GetMenu( ) ;//CWnd::GetMenu得到窗口菜单栏对象指针。CMenu* GetSubMenu( ) ;//CMenu::GetSubMenu获得指向弹出菜单对象指针UINT CheckMenuItem( );//CMenu::CheckMenuItem添加(add)check marks(选择标记)或者是删除(remove)check marks,是针对菜单项的作用BOOL SetDefaultItem();//CMenu::SetDefaultItemBOOL SetMenuItemBitmaps( );//CMenu::SetMenuItemBitmaps 设置位图标题菜单。UINT EnableMenuItem();//CMenu::EnableMenuItem使菜单项有效,无效,或变灰。BOOL SetMenu( CMenu* pMenu );//CWnd::SetMenu在当前窗口上设置新菜单或移除菜单HMENU Detach( );//CMenu::Detach Detaches a Windows menu from a CMenu object and returns the handle. 

创建一个menu项的简单过程:

CMenu menu;//定义为局部对象menu.LoadMenu(IDR_MAINFRAME);SetMenu(&menu);menu.Detach();

这里menu对象作为一个局部对象。使用Detach()从menu对象中分离窗口菜单句柄,从而当menu对象析构的时候窗口菜单资源不随之销毁。

               命令更新机制:

菜单项状态的维护是依赖于CN_UPDATE_COMMAND_UI消息,谁捕获CN_UPDATE_COMMAND_UI消息,MFC就在其中创建一个CCmdUI对象。
在后台操作系统发出WM_INITMENUPOPUP消息,然后由MFC的基类如CFrameWnd接管并创建一个CCmdUI对象和第一个菜单项相关联,调用对象成员函数DoUpdate()(注:这个函数在MSDN中没有找到说明)发出CN_UPDATE_COMMAND_UI消息,这条消息带有指向CCmdUI对象的指针。此后同一个CCmdUI对象又设置为与第二个菜单项相关联,这样顺序进行,直到完成所有菜单项。
更新命令UI处理程序仅应用于弹出式菜单项上的项目,不能应用于永久显示的顶级菜单项目。

       

          利用调用TrackPopupMenu函数,创建ContextMenu(右键菜单):

void CMenu2View::OnRButtonDown(UINT nFlags, CPoint point) {CMenu menu;menu.LoadMenu(IDR_MENU1);CMenu *pPopup = menu.GetSubMenu(0);ClientToScreen(&point);//将一个坐标点或一个矩形区域坐标转换成屏幕坐标。pPopup->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,GetParent());//在指定位置以指定的方式显示弹出菜单。CView::OnRButtonDown(nFlags, point);}
1)用资源管理器添加一个菜单资源
2)在鼠标右键消息响应函数中,加载菜单资源,并获得要显示的子菜单指针,并用该指针调用TrackPopupMenu函数便完成任务(但要注意:鼠标响应函数传进来的坐标是客户区坐标,而TrackPopupMenu函数中使用的是屏幕坐标,在调用TrackPopupMenu前要调用ClientToScreen客户区坐标到屏幕坐标的转换)

3)弹出菜单上的消息,在路由的时候,仍然遵循View-DOC-MainFrame-APP的响应顺序。

              动态菜单编程:
一些有关的比较重要的函数:

CMenu::AppendMenu //Appends a new item to the end of a menu.CMenu::CreatePopupMenu //Creates an empty pop-up menu and attaches it to a CMenu object.CMenu::InsertMenu //Inserts a new menu item at the position specified by nPosition and moves other items down the menu. CMenu::GetSubMenu //Retrieves a pointer to a pop-up menu.CWnd::GetMenu //Retrieves a pointer to the menu for this window.CMenu::DeleteMenu //Deletes an item from the menu. 
CView* GetActiveView( ) const;//获取当前视窗口指针(单文档框架中)

记录下自己的所学,虽然浅薄!!!如果我是一只蜗牛,只能慢慢向上爬!奋斗



原创粉丝点击