Mirroring Main Menu with TrackPopupMenu()

Last reviewed: November 2, 1995
Article ID: Q99806
The information in this article applies to:
  • Microsoft Windows Software Development Kit (SDK) versions 3.1
  • Microsoft Win32 Application Programming Interface (API) included with:

        - Microsoft Windows NT versions 3.5 and 3.51
        - Microsoft Windows 95 version 4.0
    

SUMMARY

A developer may want to use TrackPopupMenu() to display the same menu that is used by the main window. TrackPopupMenu() takes a pop-up menu, while GetMenu() and LoadMenu() both return handles to top level menus, and therefore you cannot use the menus returned from these functions with TrackPopupMenu(). To "mirror" the main menu, you must create pop-up menus with the same strings, style, and IDs as the main menu. To do this, use the following Windows APIs:

   GetMenu()
   CreatePopupMenu()
   GetMenuState()
   GetMenuString()
   GetSubMenu()
   AppendMenu()

MORE INFORMATION

The following code displays the same menu as the main window when the right mouse button is clicked:

// In the main window procedure...

    case WM_RBUTTONDOWN:
    {

           HMENU hMenu;            // The handle to the main menu.
           int nMenu;              // The index of the menu item.
           POINT pt;             // The point to display the track menu.
           HMENU hMenuOurs;        // The pop-up menu that we are creating.
           UINT nID;             // The ID of the menu.
           UINT uMenuState;        // The menu state.
           HMENU hSubMenu;        // A submenu.
           char szBuf[128];        // A buffer to store the menu string.

// Get the main menu.
           hMenu = GetMenu(hWnd);
           nMenu = 0;

// Create a pop-up menu.
           hMenuOurs = CreatePopupMenu();

// Get menu state will return the style of the menu
// in the lobyte of the unsigned int. Return value
// of -1 indicates the menu does not exist, and we
// have finished creating our pop up.
           while ((uMenuState =
              GetMenuState(hMenu,nMenu,MF_BYPOSITION)) != -1)
           {
                if (uMenuState != -1)
                {
// Get the menu string.
              GetMenuString(hMenu,nMenu, szBuf,128,MF_BYPOSITION);
                    if (LOBYTE(uMenuState) & MF_POPUP) // It's a pop-up
menu.
                    {
                        hSubMenu = GetSubMenu(hMenu,nMenu);
                           AppendMenu(hMenuOurs,
                    LOBYTE(uMenuState),hSubMenu,szBuf);
                    }
                    else  // Is a menu item, get the ID.
                    {
                        nID = GetMenuItemID(hMenu,nMenu);
                        AppendMenu(hMenuOurs,LOBYTE(uMenuState),nID,szBuf);

                    }
                    nMenu++;  // Get the next item.
                }
        }
        pt = MAKEPOINT(lParam);
// TrackPopupMenu expects screen coordinates.
        ClientToScreen(hWnd,&pt);
           TrackPopupMenu(hMenuOurs,
          TPM_LEFTALIGN|TPM_RIGHTBUTTON,
          pt.x,pt.y,0,hWnd,NULL);

// Because we are using parts of the main menu in our
// pop-up menu, we can't just delete the pop-up menu, because
// that would also delete the main menu. So we must
// go through the pop-up menu and remove all the items.
        while (RemoveMenu(hMenuOurs,0,MF_BYPOSITION))
            ;

// Destroy the pop-up menu.
        DestroyMenu(hMenuOurs);
    }
    break;

If the menu is never dynamically modified, then the menu hMenuOurs could be made static and created inside the WM_CREATE message, and destroyed in the WM_DESTROY message.

To see how this function works, paste this code into the MENU sample application shipped with both Microsoft Visual C/C++ and Microsoft C/C++ version 7.0 in the file MENU.C in the MenuWndProc() function.


Additional reference words: 3.10 3.50 3.51 4.00 95 popup
KBCategory: kbui
KBSubcategory: UsrMen


THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.

Last reviewed: November 2, 1995
© 1998 Microsoft Corporation. All rights reserved. Terms of Use.