Click here to Skip to main content
11,414,561 members (69,449 online)
Click here to Skip to main content

How to Use Submenus in a Context Menu Shell Extension

, 14 Feb 2003
Rate this:
Please Sign up or sign in to vote.
How to manage submenus in a context menu extension
<!-- Download Links --> <!-- Add the rest of your HTML here -->

Submenus in a context menu extension

In this article, I'll cover a tricky aspect of context menu extensions - submenus. The approach most people take at first to creating submenus leads to odd behavior in Explorer, but once you know the trick to make Explorer manage the menu correctly, it's easy! This article assumes you have a good grasp of context menu extensions. If you need a refresher, see part 1 and part 2 of my shell extension series.

Adding a submenu

This article's extension is a simple Open With... submenu, which has two items, Notepad and Internet Explorer. It behaves like the enhanced Open With menu in XP, and opens the selected file in the program that you pick. This Open With menu will demonstrate how to properly create a submenu in an extension.

What you might try first

The first thing that comes to mind is to create a new menu with CreatePopupMenu() and insert it into the menu provided by Explorer.

HRESULT COpenWithCtxMenuExt::QueryContextMenu ( 
  HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags )
{
    // If the flags include CMF_DEFAULTONLY then we shouldn't do anything.
    if ( uFlags & CMF_DEFAULTONLY )
        return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );

    // First, create and populate a submenu.
    HMENU hSubmenu = CreatePopupMenu();
    UINT uID = uidFirstCmd;

    InsertMenu ( hSubmenu, 0, MF_BYPOSITION, uID++, _T("&Notepad") );
    InsertMenu ( hSubmenu, 1, MF_BYPOSITION, uID++, _T("&Internet Explorer") );

    // Insert the submenu into the ctx menu provided by Explorer.
    <FONT color=red>InsertMenu ( hmenu, uMenuIndex, MF_BYPOSITION | MF_POPUP, 
                 (UINT_PTR) hSubmenu, _T("C&P Open With") );</FONT>

    return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, uID - uidFirstCmd );
}

This actually works fine for the context menu, however the context menu items you add are duplicated on Explorer's File menu. If you invoke the context menu repeatedly, you'll see leftover popups on the File menu:

 [Leftover submenus - 12K]

The cause is related to how Explorer cleans up its menus after extensions are invoked. The return value of QueryContextMenu() tells Explorer how many items we add, and Explorer cleans up by calculating the IDs of our items and deleting them. Explorer knows the ID of the first item (since it passes us the value as uidCmdFirst) and can calculate the IDs of the others since the IDs are assumed to be consecutive. However, the popup menu has no ID, so Explorer doesn't delete it.

The correct way

The secret is to insert the submenu using the InsertMenuItem() API. What's different about using InsertMenuItem() is that you can give the submenu an ID, which isn't possible when you use InsertMenu(). Here's the corrected QueryContextMenu() code.

HRESULT COpenWithCtxMenuExt::QueryContextMenu ( 
  HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags )
{
    // If the flags include CMF_DEFAULTONLY then we shouldn't do anything.
    if ( uFlags & CMF_DEFAULTONLY )
        return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );

    // First, create and populate a submenu.
    HMENU hSubmenu = CreatePopupMenu();
    UINT uID = uidFirstCmd;

    InsertMenu ( hSubmenu, 0, MF_BYPOSITION, uID++, _T("&Notepad") );
    InsertMenu ( hSubmenu, 1, MF_BYPOSITION, uID++, _T("&Internet Explorer") );

    // Insert the submenu into the ctx menu provided by Explorer.
<FONT color=red>    MENUITEMINFO mii = { sizeof(MENUITEMINFO) };

    mii.fMask = MIIM_SUBMENU | MIIM_STRING | MIIM_ID;
    mii.wID = uID++;
    mii.hSubMenu = hSubmenu;
    mii.dwTypeData = _T("C&P Open With");</FONT>

    <FONT color=red>InsertMenuItem ( hmenu, uMenuIndex, TRUE, &mii );</FONT>

    return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, uID - uidFirstCmd );
}

The return value this time is 3, which tells Explorer that we inserted 3 items (the two Open With items, and the submenu itself). Since all 3 items have IDs, Explorer can delete them all and completely remove our items from its menu.

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

Share

About the Author

Michael Dunn
Software Developer (Senior) VMware
United States United States
Michael lives in sunny Mountain View, California. He started programming with an Apple //e in 4th grade, graduated from UCLA with a math degree in 1994, and immediately landed a job as a QA engineer at Symantec, working on the Norton AntiVirus team. He pretty much taught himself Windows and MFC programming, and in 1999 he designed and coded a new interface for Norton AntiVirus 2000.
Mike has been a a developer at Napster and at his own lil' startup, Zabersoft, a development company he co-founded with offices in Los Angeles and Odense, Denmark. Mike is now a senior engineer at VMware.

He also enjoys his hobbies of playing pinball, bike riding, photography, and Domion on Friday nights (current favorite combo: Village + double Pirate Ship). He would get his own snooker table too if they weren't so darn big! He is also sad that he's forgotten the languages he's studied: French, Mandarin Chinese, and Japanese.

Mike was a VC MVP from 2005 to 2009.

Comments and Discussions

 
QuestionSubmenu not displaying Pin
Bartłomiej Tyla31-Aug-14 1:34
memberBartłomiej Tyla31-Aug-14 1:34 
GeneralMy vote of 5 Pin
jerry_wangjh25-Oct-11 23:11
memberjerry_wangjh25-Oct-11 23:11 
QuestionConverting this project to Dev C++ - not possible? Pin
Goran _11-Jul-08 15:51
memberGoran _11-Jul-08 15:51 
Is it possible to convert this project to Dev C++ project?

Thanks,
Gora
QuestionCan we make it dynamic? Pin
Goran _5-Jul-08 16:33
memberGoran _5-Jul-08 16:33 
QuestionHelp needed - Submenus using c# Pin
Sharath Ambati2-Apr-08 0:55
memberSharath Ambati2-Apr-08 0:55 
GeneralRe: Help needed - Submenus using c# Pin
Michael Dunn3-Apr-08 14:38
mvpMichael Dunn3-Apr-08 14:38 
Generaldefault context menu loading issue in vista........... Pin
aditya_mnit3-Mar-08 1:45
memberaditya_mnit3-Mar-08 1:45 
GeneralRe: default context menu loading issue in vista........... Pin
Michael Dunn16-Mar-08 17:16
mvpMichael Dunn16-Mar-08 17:16 
Questionhow to get the pressed item ? Pin
carabutnicolae123413-Dec-07 4:33
membercarabutnicolae123413-Dec-07 4:33 
QuestionMFT_OWNERDRAW but not really Pin
Xygorn10-Nov-06 21:14
memberXygorn10-Nov-06 21:14 
AnswerRe: MFT_OWNERDRAW but not really Pin
Michael Dunn12-Nov-06 14:47
sitebuilderMichael Dunn12-Nov-06 14:47 
QuestionWhat about using MF_BYCOMMAND Pin
highdoe19-Mar-06 20:41
memberhighdoe19-Mar-06 20:41 
AnswerRe: What about using MF_BYCOMMAND Pin
Michael Dunn22-Mar-06 12:07
sitebuilderMichael Dunn22-Mar-06 12:07 
GeneralRe: What about using MF_BYCOMMAND Pin
highdoe23-Mar-06 7:35
memberhighdoe23-Mar-06 7:35 
QuestionThere's one thing I can't understand ... Pin
Assarbad1-Jan-06 0:40
memberAssarbad1-Jan-06 0:40 
AnswerRe: There's one thing I can't understand ... Pin
Michael Dunn1-Jan-06 9:28
sitebuilderMichael Dunn1-Jan-06 9:28 
GeneralRe: There's one thing I can't understand ... Pin
Assarbad1-Jan-06 10:04
memberAssarbad1-Jan-06 10:04 
GeneralStill duplicated Menu Pin
swim071027-Dec-05 15:03
memberswim071027-Dec-05 15:03 
QuestionRe: Still duplicated Menu [modified] Pin
Nvmkpk29-Aug-06 7:49
memberNvmkpk29-Aug-06 7:49 
AnswerRe: Still duplicated Menu Pin
crino3-Sep-06 9:29
membercrino3-Sep-06 9:29 
AnswerRe: Still duplicated Menu Pin
tdinneen10-Apr-07 22:28
membertdinneen10-Apr-07 22:28 
GeneralRe: Still duplicated Menu Pin
Marx Chen13-Apr-07 16:25
memberMarx Chen13-Apr-07 16:25 
GeneralRe: Still duplicated Menu Pin
dalsegno18-Jun-07 1:40
memberdalsegno18-Jun-07 1:40 
GeneralRe: Still duplicated Menu Pin
MeNot2-Aug-09 19:58
memberMeNot2-Aug-09 19:58 
GeneralRe: Still duplicated Menu Pin
wookong22-Feb-12 0:04
memberwookong22-Feb-12 0:04 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150427.4 | Last Updated 15 Feb 2003
Article Copyright 2003 by Michael Dunn
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid