打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
解决 不能通过CCmdUI *pCmdUI改变对话框菜单状态 的问题

    我在处理一个对话框的菜单时,想为两个菜单命令添加单选标记,于是给两个菜单都添加了UPDATE_COMAND_UI 事件,在生成的函数里设置单选标记,代码如下:

Code:
  1. void CCaculatorDlg::OnUpdateToStd(CCmdUI *pCmdUI)   
  2. {   
  3.     if (!m_bSwitch)   
  4.     {   
  5.         pCmdUI->SetCheck(1);   
  6.     }   
  7.     else  
  8.     {   
  9.         pCmdUI->SetCheck(0);   
  10.     }   
  11. }   
  12.   
  13. void CCaculatorDlg::OnUpdateToSci(CCmdUI *pCmdUI)   
  14. {   
  15.     if (m_bSwitch)   
  16.     {   
  17.         pCmdUI->SetCheck(1);   
  18.     }   
  19.     else  
  20.     {   
  21.         pCmdUI->SetCheck(0);   
  22.     }   
  23. }  

    可是,程序并没有像预想的那样出现单选标记。这种方法在单文档或多文档程序中很常用,根本不会出现问题,为什么在对话框程序中就不行了呢?

    折腾了一个多小时,终于在网上找到了问题的所在和解决办法。引用原文:

Symptos:

Changing the state (enable/disable, check/uncheck, change text) of a menu item from its command user-interface (UI) handler does not work correctly if the menu is attached to a dialog box:

Code:
  1. void CTestDlg::OnUpdateFileExit(CCmdUI* pCmdUI)    
  2. {   
  3.     pCmdUI->Enable(FALSE); //Not calling the command handler, but does not show as disabled.  
  4.     pCmdUI->SetCheck(TRUE); // Does not show check mark before the text.  
  5.     pCmdUI->SetRadio(TRUE); // Does not show dot before the text.  
  6.     pCmdUI->SetText("Close"); //Does not change the text.  
  7. }  

Cause:

When a drop-down menu is displayed, the WM_INITMENUPOPUP message is sent prior to displaying the menu items. The MFCCFrameWnd::OnInitMenuPopup function iterates through the menu items and calls the update command UI handler for the item, if there is one. The appearance of each menu item is updated to reflect its state (enabled/disabled, checked/unchecked).

The update UI mechanism doesn't work for a dialog box-based application because CDialog has no OnInitMenuPopup handler and it uses CWnd's default handler, which does not call update command UI handlers for menu items.

Rusolution:

Use the following steps to resolve this problem:

1.Add an ON_WM_INITMENUPOPUP entry to the message map:

Code:
  1. BEGIN_MESSAGE_MAP(CTestDlg, CDialog)   
  2.     //}}AFX_MSG_MAP   
  3.   
  4.     ON_WM_INITMENUPOPUP()   
  5. END_MESSAGE_MAP()  

2.Add a OnInitMenuPopup member function to your dialog box class and copy the following code (note that this code is taken largely from CFrameWnd::OnInitMenuPopup in WinFrm.cpp):

Code:
  1. void CTestDlg::OnInitMenuPopup(CMenu *pPopupMenu, UINT nIndex,BOOL bSysMenu)   
  2. {   
  3.     ASSERT(pPopupMenu != NULL);   
  4.     // Check the enabled state of various menu items.  
  5.   
  6.     CCmdUI state;   
  7.     state.m_pMenu = pPopupMenu;   
  8.     ASSERT(state.m_pOther == NULL);   
  9.     ASSERT(state.m_pParentMenu == NULL);   
  10.   
  11.     // Determine if menu is popup in top-level menu and set m_pOther to  
  12.     // it if so (m_pParentMenu == NULL indicates that it is secondary popup).  
  13.     HMENU hParentMenu;   
  14.     if (AfxGetThreadState()->m_hTrackingMenu == pPopupMenu->m_hMenu)   
  15.         state.m_pParentMenu = pPopupMenu;    // Parent == child for tracking popup.  
  16.     else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL)   
  17.     {   
  18.         CWnd* pParent = this;   
  19.            // Child windows don't have menus--need to go to the top!  
  20.         if (pParent != NULL &&   
  21.            (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL)   
  22.         {   
  23.            int nIndexMax = ::GetMenuItemCount(hParentMenu);   
  24.            for (int nIndex = 0; nIndex < nIndexMax; nIndex++)   
  25.            {   
  26.             if (::GetSubMenu(hParentMenu, nIndex) == pPopupMenu->m_hMenu)   
  27.             {   
  28.                 // When popup is found, m_pParentMenu is containing menu.  
  29.                 state.m_pParentMenu = CMenu::FromHandle(hParentMenu);   
  30.                 break;   
  31.             }   
  32.            }   
  33.         }   
  34.     }   
  35.   
  36.     state.m_nIndexMax = pPopupMenu->GetMenuItemCount();   
  37.     for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax;   
  38.       state.m_nIndex++)   
  39.     {   
  40.         state.m_nID = pPopupMenu->GetMenuItemID(state.m_nIndex);   
  41.         if (state.m_nID == 0)   
  42.            continue; // Menu separator or invalid cmd - ignore it.  
  43.   
  44.         ASSERT(state.m_pOther == NULL);   
  45.         ASSERT(state.m_pMenu != NULL);   
  46.         if (state.m_nID == (UINT)-1)   
  47.         {   
  48.            // Possibly a popup menu, route to first item of that popup.  
  49.            state.m_pSubMenu = pPopupMenu->GetSubMenu(state.m_nIndex);   
  50.            if (state.m_pSubMenu == NULL ||   
  51.             (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 ||   
  52.             state.m_nID == (UINT)-1)   
  53.            {   
  54.             continue;       // First item of popup can't be routed to.  
  55.            }   
  56.            state.DoUpdate(this, TRUE);   // Popups are never auto disabled.  
  57.         }   
  58.         else  
  59.         {   
  60.            // Normal menu item.   
  61.            // Auto enable/disable if frame window has m_bAutoMenuEnable  
  62.            // set and command is _not_ a system command.  
  63.            state.m_pSubMenu = NULL;   
  64.            state.DoUpdate(this, FALSE);   
  65.         }   
  66.   
  67.         // Adjust for menu deletions and additions.  
  68.         UINT nCount = pPopupMenu->GetMenuItemCount();   
  69.         if (nCount < state.m_nIndexMax)   
  70.         {   
  71.            state.m_nIndex -= (state.m_nIndexMax - nCount);   
  72.            while (state.m_nIndex < nCount &&   
  73.             pPopupMenu->GetMenuItemID(state.m_nIndex) == state.m_nID)   
  74.            {   
  75.             state.m_nIndex++;   
  76.            }   
  77.         }   
  78.         state.m_nIndexMax = nCount;   
  79.     }   
  80. }  

原来如此,按照解决方案做,预期的效果真的出现了!

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
模态/非模态对话框不响应菜单的UPDATE
《基于MFC的OpenGL编程》Part 10 Texture Mapping
如何在文件菜单中控制最近打开的文件?
关于模态/非模态对话框不响应菜单的UPDATE
单文档窗口状态条的“就绪”怎么去掉?
CCmdUI 类
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服