–>
If you have a dialog-based application, to which you have added a menu, any OnUpdate
handlers that you included in the dialog’s message map will never be called. (Note that
the corresponding OnCommand handlers work fine).
By handling the dialog’s WM_KICKIDLE message, and mimicking MFC’s routing of its
UPDATE_UI messages, you can implement this with a little work.
The first step is to handle WM_KICKIDLE, which is #defined in afxpriv.h, by declaring
OnKickIdle(), and adding it to the message map.
//[in TESTDLG.H] class CTestDlg : public CDialog { . . . // Generated message map functions //{{AFX_MSG(CTestDlg) . . . //}}AFX_MSG afx_msg LRESULT OnKickIdle(WPARAM, LPARAM); DECLARE_MESSAGE_MAP() . . . };
#include "stdafx.h" #include "TestDlg.h" #include <afxpriv.h> . . . BEGIN_MESSAGE_MAP(CTestDlg, CDialog) //{{AFX_MSG_MAP(CTestDlg) . . . //}}AFX_MSG_MAP ON_MESSAGE(WM_KICKIDLE, OnKickIdle) END_MESSAGE_MAP()
The real work comes in defining OnKickIdle(). You need to
iterate over each item that might have an OnUpdate handler, set up a CCmdUI instance for
that item, and call CCmdUI::DoUpdate(). The OnKickIdle() I have written will update
the menu items in each of the first-level dropdown menus (e.g. the "File" menu,
the "Edit" menu, etc. from a normal app). You will need to modify it if you
have further levels of submenus. You will need a similar loop if you want to have
OnUpdate handlers for a status bar, toolbar, or specific dialog controls.
LRESULT CTestDlg::OnKickIdle(WPARAM, LPARAM) { CMenu* pMainMenu = GetMenu(); CCmdUI cmdUI; for (UINT n = 0; n < pMainMenu->GetMenuItemCount(); ++n) { CMenu* pSubMenu = pMainMenu->GetSubMenu(n); cmdUI.m_nIndexMax = pSubMenu->GetMenuItemCount(); for (UINT i = 0; i < cmdUI.m_nIndexMax;++i) { cmdUI.m_nIndex = i; cmdUI.m_nID = pSubMenu->GetMenuItemID(i); cmdUI.m_pMenu = pSubMenu; cmdUI.DoUpdate(this, FALSE); } } return TRUE; }