Download demo executable - 4 Kb
Download source - 10 Kb

Introduction
I often run into a situation where I want to apply a UI update notification
to a user-defined control in the way as it is provided by the MFC for menu
items, tool bar buttons and status bar controls. In this case a
self-defined message handler is used to properly respond to an
UPDATE_COMMAND_UI notification. Unfortunately, MFC does not support
this mechanism by default for user-defined controls, e.g. like a push
button. Well, there's still a way to manage it. Follow the step by step
procedure below to understand the principles what to do. You may want
to study the complete context in the source code of the sample.
Please note: There are two ways you have to prepare your source
code for properly applying update UI notifications to user-defined
controls. It depends on the type of window class your controls are located
in; once for a dialog class derived from CDialog and once for a view
derived from CFormView. The sample code demonstrates it by using a
dialog window. However, there's not much difference between the two ways.
Preparing a CFormView instance is described here.
But first let's take a look at the
Implementation details to perform with a CDialog
instance
- Include the MFC header file declaring private Windows
messages and macros in the source file (.cpp) of your dialog class
implementation.
#include <afxpriv.h>
- In the corresponding header file where your dialog window class is
defined declare the prototypes of the WM_KICKIDLE message handler and the
update UI handler as well. The WM_KICKIDLE message is always sent by the
system if your dialog instance is idle. This is a good time to
do some framework job.
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
[...]
afx_msg void OnKickIdle();
afx_msg void OnUpdateUserButton(CCmdUI* pCmdUI);
DECLARE_MESSAGE_MAP()
- Update your message map in .cpp file to map the
WM_KICKIDLE message and
the update notification message for the desired resource (the push button
in our sample).
BEGIN_MESSAGE_MAP(CCmdUIDemoDlg, CDialog)
ON_WM_PAINT()
[...]
ON_MESSAGE_VOID(WM_KICKIDLE, OnKickIdle)
ON_UPDATE_COMMAND_UI(IDC_BUTTON1, OnUpdateUserButton)
END_MESSAGE_MAP()
- At last implement the bodies of both message handlers
void CCmdUIDemoDlg::OnKickIdle()
{
UpdateDialogControls(this, FALSE);
}
void CCmdUIDemoDlg::OnUpdateUserButton(CCmdUI *pCmdUI)
{
pCmdUI->Enable(m_bToggle);
}
- Done! By the pCmdUI pointer you've now access to the methods of the
CCmdUI instance associated with the object, e.g. the value of the Enable() method's parameter (BOOL) decides if the control is enabled or disabled as known from a menuitem or tool bar button.
Implementation details to perform with a
CFormView instance (not part of the demo code)
To use the update notification mechanism for a CFormView instance instead
of a CDialog instance perform the following
steps by analogy:
- Include the MFC header file declaring private Windows
messages and macros in the source file (.cpp) of your dialog class
implementation.
#include <afxpriv.h>
- In the corresponding header file where your view class is
defined declare the prototypes of the WM_IDLEUPDATECMDUI message
handler and the update UI handler as well. The WM_IDLEUPDATECMDUI message
is always sent by the system if your view instance is idle.
[...]
afx_msg void OnIdleUpdateCmdUI();
afx_msg void OnUpdateUserControl(CCmdUI* pCmdUI);
DECLARE_MESSAGE_MAP()
- Update your message map in .cpp file to map the WM_IDLEUPDATECMDUI
message and the update notification message for the desired resource.
BEGIN_MESSAGE_MAP(CMyFormView, CFormView)
[...]
ON_MESSAGE_VOID(WM_IDLEUPDATECMDUI, OnIdleUpdateCmdUI)
ON_UPDATE_COMMAND_UI(IDC_MY_CONTROL, OnUpdateUserControl)
END_MESSAGE_MAP()
- At last implement the bodies of both message handlers
void CMyFormView::OnIdleUpdateCmdUI()
{
UpdateDialogControls(this, FALSE);
}
void CMyFormView::OnUpdateUserControl(CCmdUI *pCmdUI)
{
pCmdUI->Enable(...);
}
- Done!