初识MFC:ON_COMMAND_UI与ON_UPDATE_COMMAND_UI过程的区别
software:VS2012.
当我们给菜单子项添加事件处理时,发现有两个消息类型可选:COMMAND和UPDATE_COMMAND_UI,那这两个消息有什么区别呢?
分别用这两种方式添加事件处理,我们可以看到在消息映射表中添加的宏分别是:ON_COMMAND和ON_UPDATE_COMMAND_UI。
其中ON_COMMAND,我们比较熟悉,是对命令消息(来自菜单、工具条、状态栏、加速键等)的操作函数映射的宏(Remark:It indicates which function will handle a command message from a command user-interface object such as a menu item or toolbar button.)。
而ON_UPDATE_COMMAND_UI,顾名思义,就是映射更新用户界面(菜单状态)的函数的宏(There should be exactly one ON_UPDATE_COMMAND_UI macro statement in your message map for every user-interface update command that must be mapped to a message-handler function.)。
但一个较大的区别就是,ON_COMMAND是在每次选择时就已经确定了菜单的状态,ON_UPDATE_COMMAND_UI是当用户在应用的下拉菜单时,确定每个菜单项的显示状态。而且ON_COMMAND映射的函数是无参的,ON_UPDATE_COMMAND_UI是带一个(CCmdUI *)类型的参数。(封宏如下:)
1 //---ON_COMMAND--- 2 #define ON_COMMAND(id, memberFxn) \ 3 { WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \ 4 static_cast<AFX_PMSG> (memberFxn) }, 5 6 /*----------------------------------------------*/ 7 8 //---ON_UPDATE_COMMAND_UI--- 9 #define ON_UPDATE_COMMAND_UI(id, memberFxn) \ 10 { WM_COMMAND, CN_UPDATE_COMMAND_UI, (WORD)id, (WORD)id, AfxSigCmdUI, \ 11 (AFX_PMSG) \ 12 (static_cast< void (AFX_MSG_CALL CCmdTarget::*)(CCmdUI*) > \ 13 (memberFxn)) },
其中,CCmdUI没有基类。它仅在一个CCmdTarget派生类的ON_UPDATE_COMMAND_UI处理程序中使用。
举一个在ON_UPDATE_COMMAND_UI实现的例子:
1 void CViewMsgView::OnUpdateMenuUI( CCmdUI * pCmdUI ) 2 { 3 CMainFrame * pFrame = ( CMainFrame * )AfxGetMainWnd(); 4 if ( pCmdUI->m_nID == pFrame->m_nMenuItemIndex ) 5 { 6 pCmdUI->Enable(FALSE); 7 pCmdUI->SetCheck(); 8 } 9 else 10 { 11 pCmdUI->SetCheck(0); 12 } 13 }
借鉴了一下其他博友对此种设计的解释:(http://www.cnblogs.com/orez88/articles/2217823.html)
传统SDK程序要改变选单命令项状态,可以呼叫EnableMenuItem或是 CheckMenuItem,但这使得程序杂乱无章,因为你没有一个固定的位置和固定的原则处理命令项状态。MFC提供一种直接并且仍旧依赖讯息观念的方式,解决这个问题,这就是UPDATE_COMMAND_UI讯息。
其设计理念是,每当选单被拉并尚未显示之前,其命令项(以及对应之工具栏按钮)都会收到UPDATE_COMMAND_UI讯息,这个讯息和WM_COMMAND有㆒样的绕行路线,我们(程序员)只要在适当的类别上放置其处理函式,并在函式上做某些判断,便可决定如何显示命令项。
这种方法的最大好处是,不但把问题的解决方式统化,更因为 Framework传给UPDATE_COMMAND_UI处理程序的参数是个「指向CCmdUI对象的指针」,而CCmdUI对象就代表着对应的选单命令项,因此你只需呼叫 CCmdUI 所准备的,专门用来处理命令项外观的函式(如Enable或SetCheck)即可。我们的工作量大为减轻。

总之,UPDATE_COMMAND_UI方便了对菜单命令项状态的处理。

浙公网安备 33010602011771号