CommandUI Message Handling with Popup Menus

Environment: Visual C++ 6.0 sp4, Windows 2000

Have you had problems with having a popup menu in a window and not being able to get its UpdateCommandUI messages ?

Simplest solution is (if it doesnt create any kind of impropriety) making the popup menu owned by CFrameWnd derived class.
You may want to make a non CFrameWnd derived class own the menu though. This becomes a requirement when you have a dll, which
you want to provide as a plug-in. You cannot have the mainframe class of the target application which links to the dll implement
the message service routines for your popup menu! Even if it were ok, it would be pretty bad to have mainframe class have all popup
menu service code as far as even modularity is concerned.

Add ON_WM_INITMENUPOPUP() to the message map,in the class which you assign as the owner in TrackPopUpMenu(); This handles windows messsage WM_INITMENUPOPUP
send before a popup appears. TrackPopupMenu() would send this message before the menu is shown. Here is where we have to generate the
UpdateCommandUI for the menu items.

void CPvMyWnd::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
 CFrameWnd* pwndFrame = (CFrameWnd* *)AfxGetMainWnd();
 if(NULL != pwndFrame)
  pwndFrame->SendMessage(WM_INITMENUPOPUP,WPARAM(pPopupMenu->m_hMenu),
                         MAKELPARAM(nIndex,bSysMenu));
}

This will let you have a pointer to a window of some type say CMyWnd own the menu and still have update command UI messages sent for
each of the menu item ids. I would sincerely recommend you to take a look at the CFrameWnd :: OnInitPopUpMenu()function to get a full
picture as to how it generates an Update Command UI message for popup menus.

Now one more issue you may face with a popup menu having a non CFrameWnd derived class as the parent – when you initiate a new UI like
a dialog creation when the menu is still dropped down, it locks up the application because of the popup not being closed, so is the case
with combo box drop downs. CFrameWnd takes care of these and this time you will have to do it yourself. The following line of code will
help you there if you send a message to the owner window of the popup, before you want to create any other UI and it have the focus.

SendMessage(WM_CANCELMODE);

A typical situation is a client server application where u get a server message requiring a UI creation to convey some information to
the user and this can happen when the user was having fun with his popup menu and the application appears to locked up till you minimize
and restore causing popup state change. I think I wouldnt be pleased with such a treatment :), so the fix. Now combo box, he also shows
some personality traits to pick up a fight whenever some new tries to cross roads while he has a dropdown. Well use the following function

void AFXAPI AfxCancelModes(HWND hWndRcvr) declared in afximpl.h

Look in winutil.cpp in mfc source. The handle to the window that may have a child combobox with a dropped down state represents
hWndRcvr.

Going one step further How to send Update Command UI messages to any control in a given window..

 CCmdUI CmdUI;
 CmdUI.m_nID = IDC_MYBUTTON;
 CmdUI.m_pOther = CMyButtonWndClass;
 CmdUI.DoUpdate(this,FALSE);

This will send an UpdateCommandUI message to IDC_MYBUTTON to this class general scenario is that “this” is a pointer to a CDialog or
CFormView .

Well how did I know? I read CFrameWnd :: OnInitPopUpMenu().

Adios

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read