Creating context menus on menus

Raymond Chen

Raymond


Last week

we looked at menu drag/drop.
Another little-used menu feature added in Windows 2000 is
the ability to show context menus on menus.
The message is WM_MENU­RBUTTON­UP
and the flag is TPM_RECURSE.
Let’s demonstrate with a simple program.

Start with

the scratch program
,
and add

the
Move­Menu­Item function

just so our context menu can do something.

// resource header file
#define IDM_MAIN 1
#define IDM_POPUP 2
#define IDC_MOVEUP 200
#define IDC_MOVEDOWN 201
// resource file
1 MENU PRELOAD
BEGIN
    POPUP "&Test"
    BEGIN
        MENUITEM "&Red",    100
        MENUITEM "&Orange", 101
        MENUITEM "&Yellow", 102
        MENUITEM "&Green",  103
        MENUITEM "&Blue",   104
        MENUITEM "&Violet", 105
    END
END
2 MENU PRELOAD
BEGIN POPUP ""
    BEGIN
        MENUITEM "Move &Up",   IDC_MOVEUP
        MENUITEM "Move &Down", IDC_MOVEDOWN
        MENUITEM SEPARATOR
        MENUITEM "&Cancel",    IDCANCEL
    END
END
// scratch.cpp
#define HANDLE_WM_MENURBUTTONUP(hwnd, wParam, lParam, fn) \
    ((fn)((hwnd), (UINT)(wParam), (HMENU)(lParam)), 0L)
void OnMenuRButtonUp(HWND hwnd, UINT uPos, HMENU hmenu)
{
 if (hmenu == GetSubMenu(GetMenu(hwnd), 0)) {
  HMENU hmenuPopup = LoadMenu(g_hinst, MAKEINTRESOURCE(IDM_POPUP));
  if (hmenuPopup) {
   if (uPos == 0) {
    EnableMenuItem(hmenuPopup, IDC_MOVEUP, MF_DISABLED | MF_GRAYED);
   }
   if (uPos == GetMenuItemCount(hmenu) - 1) {
    EnableMenuItem(hmenuPopup, IDC_MOVEDOWN, MF_DISABLED | MF_GRAYED);
   }
   DWORD dwPos = GetMessagePos();
   UINT idCmd = TrackPopupMenuEx(GetSubMenu(hmenuPopup, 0),
                 TPM_RECURSE | TPM_RETURNCMD,
                 GET_X_LPARAM(dwPos),
                 GET_Y_LPARAM(dwPos), hwnd, NULL);
   switch (idCmd) {
    case IDC_MOVEUP:
     MoveMenuItem(hmenu, uPos, uPos - 1);
     break;
    case IDC_MOVEDOWN:
     MoveMenuItem(hmenu, uPos, uPos + 2);
     break;
   }
   DestroyMenu(hmenuPopup);
  }
 }
}
    HANDLE_MSG(hwnd, WM_MENURBUTTONUP, OnMenuRButtonUp);
// InitApp function
    wc.lpszMenuName = MAKEINTRESOURCE(IDM_MAIN);

When we receive the
WM_MENU­RBUTTON­UP message
and confirm that the menu is the one we support,
we create the popup menu and display it at the mouse
location (obtained via Get­Message­Pos)
with the TPM_RECURSE flag,
indicating that this is a pop-up menu for a pop-up menu.
(We also use TPM_RETURN­CMD,
but that’s nothing new.)
If the user chose to move the item up or down, we move it up or down.

That’s all.
There really isn’t much here, but I figured I’d just
write a sample program just to show how it’s done.

Raymond Chen
Raymond Chen

Follow Raymond   

0 comments

Comments are closed.