Using ON_UPDATE_COMMAND_UI with menu items and controls (2)


Application Security Testing: An Integral Part of DevOps


 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 LRESULT OnKickIdle(WPARAM, LPARAM);
 . . .
#include "stdafx.h"
#include "TestDlg.h"
#include <afxpriv.h>
. . . 
 . . .

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.

 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;

Download demo project - 10 KB


  • Handling OnUpdate() processing for menu items

    Posted by Legacy on 10/16/2001 12:00am

    Originally posted by: Anonymous

    How to do this for a CPropertyPage derived class ?????

    Please help...

  • Smaller, faster and efficient (I hope) K.I.S.S. in other word.

    Posted by Legacy on 06/14/2001 12:00am

    Originally posted by: Leonid Prokopovich

    There is no need to update menu items in all submenus. You should update only those one which about to show.
    There is simple and efficient solution. I'm using it for a long time.

    1. Add WM_INITMENUPOPUP handler.
    2. Modify OnInitMenuPopup() as follows

    void CMyDlg::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
    CCmdUI CmdUI;
    UINT nIndex;

    // Skip system menu from processing
    if( FALSE != bSysMenu )

    CmdUI.m_nIndexMax = pPopupMenu->GetMenuItemCount();
    for( nIndex = 0; nIndex < CmdUI.m_nIndexMax; ++nIndex )
    CmdUI.m_nIndex = nIndex;
    CmdUI.m_nID = pPopupMenu->GetMenuItemID(i);
    CmdUI.m_pMenu = pPopupMenu;

    // There are two options. You can choose the one by removing comments
    // Option 1. All handlers are in dialog
    // CmdUI.DoUpdate( this, TRUE );

    // Option 2. There are handlers in dialog and controls
    CmdUI.DoUpdate( this, FALSE );
    // If dialog handler doesn't change state route update
    // request to child controls. The last DoUpdate will
    // disable menu item with no handler
    if( FALSE == CmdUI.m_bEnableChanged )
    CmdUI.DoUpdate( m_pControl_1, FALSE );
    if( FALSE == CmdUI.m_bEnableChanged )
    CmdUI.DoUpdate( m_pControl_Last, TRUE );

  • Avoid KickIdle,A simple way toUpdate!!

    Posted by Legacy on 11/30/2000 12:00am

    Originally posted by: Sreedharan

    I am using OnMenuSelect() function rather.
    So, cmdUI.DoUpdate() function is called whenever user
    Selects a menu item,instead of calling it from OnKickIdle().

    void CXXXDlg::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
    CCmdUI cmdUI;
    CMenu* pMainMenu = GetMenu();
    CMenu* pSubMenu = pMainMenu-> GetSubMenu(nItemID);
    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);



  • Re : Code hoards CPU time

    Posted by Legacy on 11/02/2000 12:00am

    Originally posted by: Yair Konfino

    It`s true that the CPU is working hard in this case !!!
    Spy++ shows why .
    WM_KICKIDLE is passed to the window thousands of times
    repeatedly .
    The solution is to use :
    It`s working for me .

  • Updating popup menus

    Posted by Legacy on 07/25/2000 12:00am

    Originally posted by: Damian Biollo

    John Wismar's code works good, except that OnKickIdle() doesn't get called during TrackPopupMenu().  

    A simpler solution is to handle the WM_INITMENUPOPUP message; OnInitMenuPopup() will be called automatically for each popup sub-menu, so you don't even need to code the UpdateMenu function recursively.

    As a bonus, MS has actually documented OnInitMenuPopup(), unlike the undocumented kick-idle.

    Like so:


    void MyDialog::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)

    void MyDialog::UpdateMenu(CMenu* pMenu)
    CCmdUI cmdUI;
    cmdUI.m_nIndexMax = pMenu->GetMenuItemCount();
    for (UINT n = 0; n < cmdUI.m_nIndexMax; ++n)
    CMenu* pSubMenu = pMenu->GetSubMenu(n);
    if (pSubMenu == NULL)
    cmdUI.m_nIndex = n;
    cmdUI.m_nID = pMenu->GetMenuItemID(n);
    cmdUI.m_pMenu = pMenu;
    cmdUI.DoUpdate(this, FALSE);

  • Code hoards CPU time

    Posted by Legacy on 03/02/2000 12:00am

    Originally posted by: Clinton Morell

    I found that the OnKickIdle() code tended to hoard CPU time on my computer and it was keeping other programs from getting enough CPU cycles.

    Adding "Sleep(1)" at the beginning of the OnKickIdle() function fixed the problem for me, your mileage may vary.

  • How to implement this for a toolbar control.

    Posted by Legacy on 04/19/1999 12:00am

    Originally posted by: Brandon Jackson

    First, follow Mr. Wismar's instructions for adding OnUpdate() handling for menus.

    Then, from ../MFC/SRC/BARTOOL.CPP, grab the definition for CToolCmdUI.

    In OnKickIdle() add

    (m_tbr is a CToolBar derived class)

    CToolCmdUI state;
    state.m_pOther = &m_tbr;

    state.m_nIndexMax = m_tbr.GetToolBarCtrl().GetButtonCount();
    for ( state.m_nIndex = 0; state.m_nIndex < state.m_nIndexMax; state.m_nIndex++ )
    state.m_nID = m_tbr.GetItemID( state.m_nIndex );

    // ignore separators
    if (!(m_tbr.GetButtonStyle( state.m_nIndex ) & TBSTYLE_SEP))
    // allow the owner to process the update
    state.DoUpdate( this, TRUE );

  • How to implement this for toolbar control?

    Posted by Legacy on 04/15/1999 12:00am

    Originally posted by: Andrey

    I have a Tabbed Property sheet application.

    The first Property page has a toolbar control and a list control. The list control has a popup menu with commands applied to it. It has ON_UPDATE_COMMAND_UI for these commands as it knows when to disable items.

    I need that toolbar control that belongs to list's parent to duplicate the commands in the menu (including auto disabling).

    Do you know how to implement this?

    Thanks a lot!

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date
We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.