Click here to Skip to main content
15,867,308 members
Articles / Desktop Programming / MFC
Article

Getting a Handler Function to a Specific Popup Menu

Rate me:
Please Sign up or sign in to vote.
4.17/5 (6 votes)
2 Feb 20063 min read 47.3K   617   20   2
This article explains how to get a call to a handler, when a specific popup-menu is about to be opened.

Foreword

This article shows how to easily and effectively get a call to a handler function, when a specific popup menu is opened.

The Problem

Working with MFC, from time to time, you want to get a callback from the framework when a popup menu is about to be opened. The framework indeed sends this kind of callbacks, and you can easily get it by:

ON_WM_INITMENUPOPUP()

which leads to:

OnInitMenuPopup()

But note that this handler is called for every popup menu in your current window. This is good if you want to do something generic for all menus, but what-if you need some special treatment for a specific popup-menu? Then, you need to know which is the popup menu-item that on clicking has opened this menu. The OnInitMenuPopup() callback does not tell you who the "parent" of the opened-popup menu is; it only tells you which the popup menu that is about to be opened is. So what are we going to do?

Solution

The Design

Well, I think that the best solution for this problem is to "mark" the popup-menu item somehow, and then, when the callback is called, we will search for this mark. If we find it - we have found our popup-menu item. Otherwise - oh, well. Do nothing.

The Implementation

Let's create the handler function that will be called when our popup menu is about to be opened. Soon we will see how we make this happen; but for a start, let's define it, first. It can be a global function, or it can be a method in some class. The only thing we have to take into account is that the caller (that generates the call to our handler, CMainFrame, for example) will have to know (by include) this class.

//the handler method that is called
//whenever a marked-up popup menu is about to be opened:
void OnMarkedPopupMenu(CMenu* pPopupMenu);

Wherever you initialize your GUI settings (or may I say, your controls... for example: CMainFrame::OnCreate()), add the "mark" to the specific popup menu. In this specific example, I add a new popup menu item (in runtime) to an improvised location (this is not the main point of this article...), and give it an improvised name, "Nikon D70s" (my camera...). Then, mark this menu (we mark the popup menu itself, not the menu-item that opens it!!), using the MENUINFO struct. This struct has the dwMenuData member, that we can use for this purpose. This member is a DWORD, so you can use a constant as a marker, or allocate a string and pass the pointer to it. Here I use the simple constant c_nCode (that is declared somewhere else in my code).

CMenu* pPopupMenu = AddPopupMenu(this, 2, 4, "Nikon D70s");
MENUINFO MenuInfo;
MenuInfo.cbSize = sizeof(MENUINFO);
MenuInfo.fMask = MIM_MENUDATA;
MenuInfo.dwMenuData = c_nCode;
//mark the popup menu:
pPopupMenu->SetMenuInfo( &MenuInfo );

Note that "Nikon D70s" is the item, clicking on it opens the popup menu. We mark the popup menu, not the item, since in OnInitMenuPopup() we get a pointer to the menu, not to the item.

Now, we need to implement the OnInitMenuPopup() callback. This callback is called every time a popup menu is about to be opened. So we need to check now if this popup menu was the one that we have marked up in the initialization. If it is - call the handler function.

void CMainFrame::OnInitMenuPopup( CMenu* pPopupMenu, 
                         UINT nIndex, BOOL bSysMenu )
{
   MENUINFO MenuInfo;
   MenuInfo.cbSize = sizeof(MENUINFO);
   MenuInfo.fMask = MIM_MENUDATA;
   MenuInfo.dwMenuData = 0;
   VERIFY( pPopupMenu->GetMenuInfo( &MenuInfo ) );
   if(MenuInfo.dwMenuData == c_nCode)
   {
      //call the handler!!!
      OnMarkedPopupMenu(pPopupMenu);
   }
}

That's it!

Note that we can mark different popup menus with different "codes" (or strings) and then, in CMainFrame::OnInitMenuPopup, we will have to check this and delegate to different handlers.

Last Remark - MENUINFO

One last thing before we go: you might encounter a nice obstacle, when the compiler will shout on you the error:

error C2065: 'MENUINFO' : undeclared identifier

Well, the problem is not "include", since including windows.h is enough, and you probably has done so in your stdafx.h. So what is the problem? Well, MFC versions are the problem this time. Just put:

#define WINVER 0x500

in the top of your stdafx.h file. This will solve this problem.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Israel Israel
working for Intel

My Linkedin Profile

Visit my photography gallery

Comments and Discussions

 
QuestionMiscategorized? Pin
Ravi Bhavnani2-Feb-06 10:24
professionalRavi Bhavnani2-Feb-06 10:24 
Thanks for your article.

Can you modify its category to MFC/C++ - Menus[^]. It seems to be categorized under C#/.NET - Menus & Toolbars[^]. Thanks!

/ravi

My new year's resolution: 2048 x 1536
Home | Music | Articles | Freeware | Trips
ravib(at)ravib(dot)com

AnswerRe: Miscategorized? Pin
Smitha Nishant2-Feb-06 11:11
protectorSmitha Nishant2-Feb-06 11:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.