–>
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;
}