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

来源:转载

      首先,在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操作过程中,几个函数需要了解:

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

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

1 CMenu menu;//定义为局部对象
2 menu.LoadMenu(IDR_MAINFRAME);
3 SetMenu(&menu);
4 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(右键菜单):

1 void CMenu2View::OnRButtonDown(UINT nFlags, CPoint point) 
2 {
3 CMenu menu;
4 menu.LoadMenu(IDR_MENU1);
5 CMenu *pPopup = menu.GetSubMenu(0);
6 ClientToScreen(&point);//将一个坐标点或一个矩形区域坐标转换成屏幕坐标。
7 pPopup->TrackPopupMenu(TPM_LEFTALIGN,point.x,point.y,GetParent());//在指定位置以指定的方式显示弹出菜单。
8 CView::OnRButtonDown(nFlags, point);
9 }

1)用资源管理器添加一个菜单资源
2)在鼠标右键消息响应函数中,加载菜单资源,并获得要显示的子菜单指针,并用该指针调用TrackPopupMenu函数便完成任务(但要注意:鼠标响应函数传进来的坐标是客户区坐标,而TrackPopupMenu函数中使用的是屏幕坐标,在调用TrackPopupMenu前要调用ClientToScreen客户区坐标到屏幕坐标的转换)

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

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

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

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


分享给朋友:
您可能感兴趣的文章:
随机阅读: