MFC教程(4)-- 消息映射的实现(2)
2010-03-25 20:33:48 来源:WEB开发网DoUpdate作以下事情:
首先,发送状态更新命令消息给参数1表示的命令目标:调用pTarget->OnCmdMsg(m_nID, CN_UPDATE_COMMAND_UI, this, NULL)发送m_nID对象的通知消息CN_UPDATE_COMMAND_UI。OnCmdMsg的参数3取值this,包含了当前要更新的用户接口对象的信息。
然后,如果参数2为TRUE,调用pTarget->OnCmdMsg(m_nID, CN_COMMAND, this, &info)测试命令消息m_nID是否被处理。这时,OnCmdMsg的第四个参数非空,表示仅仅是测试,不是真的要派发消息。如果没有提供命令消息m_nID的处理函数,则禁止用户对象m_nID,否则使之可用。
从上面的讨论可以知道:通过其结构,一个CCmdUI对象标识它表示了哪一个用户接口对象,如果是菜单接口对象,pMenu表示了要更新的菜单对象;如果是工具条,pOther表示了要更新的工具条窗口对象,nID表示了工具条按钮ID。
所以,由参数上状态更新消息的消息处理函数就知道要更新什么接口对象的状态。例如,第1节的函数OnUpdateEditPaste,函数参数pCmdUI表示一个菜单对象,需要更新该菜单对象的状态。
通过其成员函数,一个CCmdUI可以更新、改变用户接口对象的状态。例如,CCmdUI可以管理菜单和对话框控制的状态,调用Enable禁止或者允许菜单或者控制子窗口,等等。
所以,函数OnUpdateEditPaste可以直接调用参数的成员函数(如pCmdUI->Enable)实现菜单对象的状态更新。
由于接口对象的多样性,其他接口对象将从CCmdUI派生出管理自己的类来,覆盖基类的有关成员函数如Enable等,提供对自身状态更新的功能。例如管理状态条和工具栏更新的CStatusCmdUI类和CToolCmdUI类。
自动更新用户接口对象状态的机制
MFC提供了分别用于更新菜单和工具条的两种途径。
更新菜单状态
当用户对菜单如File单击鼠标时,就产生一条WM_INITMENUPOPUP消息,边框窗口在菜单下拉之前响应该消息,从而更新该菜单所有项的状态。
在应用程序开始运行时,边框也会收到WM_INITMENUPOPUP消息。
更新工具条等状态
当应用程序进入空闲处理状态时,将发送WM_IDLEUPDATECMDUI消息,导致所有的工具条用户对象的状态处理函数被调用,从而改变其状态。WM_IDLEUPDATECMDUI是MFC自己定义和使用的消息。
在窗口初始化时,工具条也会收到WM_IDLEUPDATECMDUI消息。
菜单状态更新的实现
MFC让边框窗口来响应WM_INITMENUPOPUP消息,消息处理函数是OnInitMenuPopup,其原型如下:
afx_msg void CFrameWnd::OnInitMenuPopup( CMenu* pPopupMenu,
UINT nIndex, BOOL bSysMenu );
第一个参数指向一个CMenu对象,是当前按击的菜单;第二个参数是菜单索引;第三个参数表示子菜单是否是系统控制菜单。
函数的处理:
如果是系统控制菜单,不作处理;否则,创建CCmdUI对象state,给它的各个成员如m_pMenu,m_pParentMenu,m_pOther等赋值。
对该菜单的各个菜单项,调函数state.DoUpdate,用CCmdUI的DoUpdate来更新状态。DoUpdate的第一个参数是this,表示命令目标是边框窗口;在CFrameWnd的成员变量m_bAutoMenuEnable为TRUE时(表示如果菜单m_nID没有对应的消息处理函数或状态更新函数,则禁止它),把DoUpdate的第二个参数bDisableIfNoHndler置为TRUE。
顺便指出,m_bAutoMenuEnable缺省时为TRUE,所以,应用程序启动时菜单经过初始化处理,没有提供消息处理函数或状态更新函数的菜单项被禁止。
更多精彩
赞助商链接