本人在 VC2010 开发环境下成功测试
问题:一般情况下我们用UPDATE_COMMAND_UI来修改菜单的状态(enable/disable, check/uncheck, change text),但这个方法在一个基于对话框上的菜单却没有效果。








原因分析:当显示一个下拉的菜单的时候,在显示菜单前会发送WM_INITMENUPOPUP消息。而CFrameWnd:: OnInitMenuPopup函数会刷新这个菜单项,同时如果有UPDATE_COMMAND_UI响应函数,则调用它。通过它来更新反应每个菜单的外观效果(enabled/disabled, checked/unchecked).
在一个基于对话框的程序中,因为没有OnInitMenuPopup函数,所以不会调用UPDATE_COMMAND_UI响应函数,而是使用了CWnd类的默认处理, 这种处理没有调用UPDATE_COMMAND_UI响应函数。
解决方法如下:
第一步:
在对话框类的.cpp文件,添加一个ON_WM_INITMENUPOPUP入口到消息映射里面




第二步:
在对话框类的.h文件添加消息函数声明。





注意:以上两步也可以直接使用类向导添加 ON_WM_INITMENUPOPUP 消息。
第三步:
在对话框类的.cpp文件添加如下函数代码(大部分代码取自WinFrm.cpp文件的函数 CFrameWnd::OnInitMenuPopup):
void C******Dlg::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu) { //CDialogEx::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu); // TODO: 在此处添加消息处理程序代码 ASSERT(pPopupMenu != NULL); CCmdUI state; state.m_pMenu = pPopupMenu; ASSERT(state.m_pOther == NULL); ASSERT(state.m_pParentMenu == NULL); HMENU hParentMenu; if (AfxGetThreadState()->m_hTrackingMenu == pPopupMenu->m_hMenu) state.m_pParentMenu = pPopupMenu; else if ((hParentMenu = ::GetMenu(m_hWnd)) != NULL) { CWnd* pParent = this; if (pParent != NULL && (hParentMenu = ::GetMenu(pParent->m_hWnd)) != NULL) { int nIndexMax = ::GetMenuItemCount(hParentMenu); for (int nIndex = 0; nIndex < nIndexMax; nIndex++) { if (::GetSubMenu(hParentMenu, nIndex) == pPopupMenu->m_hMenu) { state.m_pParentMenu = CMenu::FromHandle(hParentMenu); break; } } } } state.m_nIndexMax = pPopupMenu->GetMenuItemCount(); for (state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; state.m_nIndex++) { state.m_nID = pPopupMenu->GetMenuItemID(state.m_nIndex); if (state.m_nID == 0) continue; ASSERT(state.m_pOther == NULL); ASSERT(state.m_pMenu != NULL); if (state.m_nID == (UINT)-1) { state.m_pSubMenu = pPopupMenu->GetSubMenu(state.m_nIndex); if (state.m_pSubMenu == NULL || (state.m_nID = state.m_pSubMenu->GetMenuItemID(0)) == 0 || state.m_nID == (UINT)-1) { continue; } state.DoUpdate(this, TRUE); } else { state.m_pSubMenu = NULL; state.DoUpdate(this, FALSE); } UINT nCount = pPopupMenu->GetMenuItemCount(); if (nCount < state.m_nIndexMax) { state.m_nIndex -= (state.m_nIndexMax - nCount); while (state.m_nIndex < nCount && pPopupMenu->GetMenuItemID(state.m_nIndex) == state.m_nID) { state.m_nIndex++; } } state.m_nIndexMax = nCount; } }
更详细的信息可参考
http://support.microsoft.com/default.aspx?scid=kb;en-us;242577