消息的捕获流程:
首先是CView最先捕获消息,如果在CView消息映射中没有对消息进行处理,则由CDoc进行捕获处理,否则则交由CMainFrame处理,否则交由CWinApp处理。
消息的分类:
标准消息:除WM_COMMAND之外,所有WM_开头的消息,从CWnd派生的类,都可以接收到该类消息;
命令消息:来自菜单、加速键或工具栏按钮的消息,这类消息都以WM_COMMAND呈现。在MFC中,通过菜单项的标识(ID)来区分不同的命令消息;在SDK中,通过消息的wParam参数识别。从CCmdTarget派生的类,都可以接收到这类消息。
通告消息:由控件产生的消息,比如按钮的单击,列表框的选择等均产生该类消息,为的是向其父窗口(通常是对话框)通知事件的发生,这类消息也是以WM_COMMAND呈现的。从CCmdTarget派生的类,都可以接收到该类消息。
标准消息和命令消息是向本窗口发送的消息;通告消息是由子窗口向父窗口发送的消息,如按钮等本身也是一个窗口,当本身状态改变时向其父类发送消息。
MFC命令消息的路由:
下面,我们以Menu这个程序为例,来看看
响应菜单项命令的顺序依次是:视类、文档类、框架类,最后才是应用程序类。
菜单命令消息路由的具体过程:当单击某个菜单项时,最先接收到这个菜单命令消息的是框架类。框架类将把接收到的这个消息交给它的子窗口。即视类,由视类首先进行处理。视类首先格局命令消息映射机制查找自身是否对此消息进行了响应,如果响应了,就调用相应响应函数对这个消息进行处理,消息路由过程结束;如果视类没有对此命令消息做出响应,就交由文档类,文档类同样查找自身是否对这个菜单命令进行了响应,如果响应了,就有文档类的命令消息响应函数进行处理,路由过程结束。如果文档类也未做响应,就把这个命令消息交还给视类,后者又把该消息交还给框架类。框架类查看自己是否对这个命令消息进行了响应,如果它也没有做出响应,就把这个菜单命令消息交给应用程序类,由后者来进行处理。
标准消息是不需要路由的,标准消息总是发送给一个指定的窗口,由指定的窗口进行消息响应,而命令消息和控件消息则有一个消息的路由选择(命令消息有些是框架窗口的,有些是视类窗口的,因此消息需要路由)。
标记菜单:
访问子菜单只能够通过索引进行访问,访问子菜单项可以通过子菜单项的索引或者它的标识进行访问。
GetMenu():返回框架窗口的菜单栏CMenu的指针。
CMenu有一个函数GetSubMenu()返回一个指向子菜单的CMenu指针。
GetMenu()->GetSubMenu(0)->CheckMenuItem(0,MF_BYPOSITION|MF_CHECKED);
GetMenu获取菜单栏,GetSubMenu获取子菜单,CheckMenuItem对子菜单项进行操作,创建一个标记菜单。
设置一个图形标记菜单:SetMenuItemBitmaps()。
设置缺省菜单:SetDefaultItem(),一个子菜单中只能有一个缺省菜单项。
MFC命令更新机制:
菜单项状态的维护是依赖于CN_UPDATE_COMMAND_UI消息,谁捕获CN_UPDATE_COMMAND消息,MFC就在其中创建一个CCmdUI对象,我们可以通过手工活利用Class Wizard在消息映射中添加ON_UPDATE_COMMAND_UI宏来捕获CN_UPDATE_COMMAND_UI消息。
在后台所做的工作是:操作系统发出WM_INITMENEPOPUP消息,然后由MFC的基类如CFrameWnd接管,它创建一个CCmdUI对象,并与第一个菜单项相关联,调用对象的一个函数DoUpdate(),这个函数发出CN_UPDATE_COMMAND_UI消息,这个消息带有指向CCmdUI对象的指针。同一个CCmdUI对象就设置为与第二个菜单项相关联,这样顺序执行,直到完成所有菜单项。
从第一个菜单项开始更新,一直更新到最后一个,如果该菜单项捕获了该消息,就对该菜单项进行更新。
更新命令UI处理程序仅应用于弹出式菜单项上的项目,不能应用于永久显示的顶级菜单项目。