2 out of 9 rated this helpful - Rate this topic

TrackPopupMenu function

Applies to: desktop apps only

Displays a shortcut menu at the specified location and tracks the selection of items on the menu. The shortcut menu can appear anywhere on the screen.

Syntax

BOOL WINAPI TrackPopupMenu(
  __in      HMENU hMenu,
  __in      UINT uFlags,
  __in      int x,
  __in      int y,
  __in      int nReserved,
  __in      HWND hWnd,
  __in_opt  const RECT *prcRect
);

Parameters

hMenu [in]

Type: HMENU

A handle to the shortcut menu to be displayed. The handle can be obtained by calling CreatePopupMenu to create a new shortcut menu, or by calling GetSubMenu to retrieve a handle to a submenu associated with an existing menu item.

uFlags [in]

Type: UINT

Use zero of more of these flags to specify function options.

Use one of the following flags to specify how the function positions the shortcut menu horizontally.

ValueMeaning
TPM_CENTERALIGN
0x0004L

Centers the shortcut menu horizontally relative to the coordinate specified by the x parameter.

TPM_LEFTALIGN
0x0000L

Positions the shortcut menu so that its left side is aligned with the coordinate specified by the x parameter.

TPM_RIGHTALIGN
0x0008L

Positions the shortcut menu so that its right side is aligned with the coordinate specified by the x parameter.

 

Use one of the following flags to specify how the function positions the shortcut menu vertically.

ValueMeaning
TPM_BOTTOMALIGN
0x0020L

Positions the shortcut menu so that its bottom side is aligned with the coordinate specified by the y parameter.

TPM_TOPALIGN
0x0000L

Positions the shortcut menu so that its top side is aligned with the coordinate specified by the y parameter.

TPM_VCENTERALIGN
0x0010L

Centers the shortcut menu vertically relative to the coordinate specified by the y parameter.

 

Use the following flags to control discovery of the user selection without having to set up a parent window for the menu.

ValueMeaning
TPM_NONOTIFY
0x0080L

The function does not send notification messages when the user clicks a menu item.

TPM_RETURNCMD
0x0100L

The function returns the menu item identifier of the user's selection in the return value.

 

Use one of the following flags to specify which mouse button the shortcut menu tracks.

ValueMeaning
TPM_LEFTBUTTON
0x0000L

The user can select menu items with only the left mouse button.

TPM_RIGHTBUTTON
0x0002L

The user can select menu items with both the left and right mouse buttons.

 

Use any reasonable combination of the following flags to modify the animation of a menu. For example, by selecting a horizontal and a vertical flag, you can achieve diagonal animation.

ValueMeaning
TPM_HORNEGANIMATION
0x0800L

Animates the menu from right to left.

TPM_HORPOSANIMATION
0x0400L

Animates the menu from left to right.

TPM_NOANIMATION
0x4000L

Displays menu without animation.

TPM_VERNEGANIMATION
0x2000L

Animates the menu from bottom to top.

TPM_VERPOSANIMATION
0x1000L

Animates the menu from top to bottom.

 

For any animation to occur, the SystemParametersInfo function must set SPI_SETMENUANIMATION. Also, all the TPM_*ANIMATION flags, except TPM_NOANIMATION, are ignored if menu fade animation is on. For more information, see the SPI_GETMENUFADE flag in SystemParametersInfo.

Use the TPM_RECURSE flag to display a menu when another menu is already displayed. This is intended to support context menus within a menu.

For right-to-left text layout, use TPM_LAYOUTRTL. By default, the text layout is left-to-right.

x [in]

Type: int

The horizontal location of the shortcut menu, in screen coordinates.

y [in]

Type: int

The vertical location of the shortcut menu, in screen coordinates.

nReserved [in]

Type: int

Reserved; must be zero.

hWnd [in]

Type: HWND

A handle to the window that owns the shortcut menu. This window receives all messages from the menu. The window does not receive a WM_COMMAND message from the menu until the function returns. If you specify TPM_NONOTIFY in the uFlags parameter, the function does not send messages to the window identified by hWnd. However, you must still pass a window handle in hWnd. It can be any window handle from your application.

prcRect [in, optional]

Type: const RECT*

Ignored.

Return value

Type: BOOL

If you specify TPM_RETURNCMD in the uFlags parameter, the return value is the menu-item identifier of the item that the user selected. If the user cancels the menu without making a selection, or if an error occurs, the return value is zero.

If you do not specify TPM_RETURNCMD in the uFlags parameter, the return value is nonzero if the function succeeds and zero if it fails. To get extended error information, call GetLastError.

Remarks

Call GetSystemMetrics with SM_MENUDROPALIGNMENT to determine the correct horizontal alignment flag (TPM_LEFTALIGN or TPM_RIGHTALIGN) and/or horizontal animation direction flag (TPM_HORPOSANIMATION or TPM_HORNEGANIMATION) to pass to TrackPopupMenu or TrackPopupMenuEx. This is essential for creating an optimal user experience, especially when developing Microsoft Tablet PC applications.

To specify an area of the screen that the menu should not overlap, use the TrackPopupMenuEx function

To display a context menu for a notification icon, the current window must be the foreground window before the application calls TrackPopupMenu or TrackPopupMenuEx. Otherwise, the menu will not disappear when the user clicks outside of the menu or the window that created the menu (if it is visible). If the current window is a child window, you must set the (top-level) parent window as the foreground window.

However, when the current window is the foreground window, the second time this menu is displayed, it appears and then immediately disappears. To correct this, you must force a task switch to the application that called TrackPopupMenu. This is done by posting a benign message to the window or thread, as shown in the following code sample:



   SetForegroundWindow(hDlg);

   // Display the menu
   TrackPopupMenu(   hSubMenu,
                     TPM_RIGHTBUTTON,
                     pt.x,
                     pt.y,
                     0,
                     hDlg,
                     NULL);

   PostMessage(hDlg, WM_NULL, 0, 0);
 

Examples

For an example, see Displaying a Shortcut Menu.

Requirements

Minimum supported client

Windows 2000 Professional

Minimum supported server

Windows 2000 Server

Header

Winuser.h (include Windows.h)

Library

User32.lib

DLL

User32.dll

See also

Reference
CreatePopupMenu
GetSubMenu
TrackPopupMenuEx
WM_COMMAND
Conceptual
Menus

 

 

Send comments about this topic to Microsoft

Build date: 2/3/2012

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
TIP for Dynamic Pop Menu without needing UI Handers
I spent over a day on this and it ended it being so simple. The docs should make a note TPM_NONOTIFY will not only requiire handers, but necessary if you want the dynamically added menu items to be enabled (not grayed out). <div class="communityContentAnnotationBody"> Example code: void CmyControl::DoPopupMenu() { CMenu menu; menu.CreatePopupMenu(); int nBaseID = 0x0E00; // Your own base id menu.AppendMenu(uFlags, nBaseId+1, _T("Item #1")); menu.AppendMenu(uFlags, nBaseId+2, _T("Item #2")); menu.AppendMenu(uFlags, nBaseId+3, _T("Item #3")); .... menu.AppendMenu(uFlags, nBaseId+n, _T("Item #n")); POINT pt; GetCursorPos(&pt); // TMP_NONOTIFY required for no UI handlers UINT tpmFlags = TPM_LEFTALIGN|TPM_RETURNCMD|TPM_NONOTIFY; int nRes = menu.TrackPopupMenu(tpmFlags,pt.x,pt.y,AfxGetApp()->GetMainWnd()); // // handle nRes // int nIndex = nRes-nBaseID; .... return; } </div> Maybe this tip will save other "Non-Smart" people some time. :)
Open a submenu without clicking
I have pondered and bothered and finally found that I have to use the TPM_RECURSE flag to be able to open submenus with WM_MENUSELECT.
Unfortunately my headers don't support the latest constants and the value for TPM_RECURSE is not mentioned anywhere, as opposed to the other constants.

Here it is: TPM_RECURSE = 0x0001L

Happy coding :D
Dead lock if have called RegisterRawInputDevices.
Result:
Deadlock in TrackPopupMenu if plug/unplug mouse when pop menu is open.

Repro steps:
1. create a simplest win32 application, which has a default window
2. Add popmenu code and rawinput related dialog
    Code in message loop:
        case WM_CREATE:
            ConfigRawInput( hWnd, RIDEV_INPUTSINK | RIDEV_DEVNOTIFY );
            break;
        case WM_CONTEXTMENU:
            OpenRightClickMenu(hWnd);
        break;
    The functions called:

        #define HID_USAGE_PAGE_GENERIC ((USHORT) 0x01)
        #define HID_USAGE_GENERIC_MOUSE ((USHORT) 0x02)
        #define HID_USAGE_PAGE_CONSUMER ((USHORT) 0x0C)
        #define HID_USAGE_CONSUMERCTRL ((USHORT) 0x01)

        void ConfigRawInput( HWND hWnd, DWORD flags )
        {
            HWND notifyWindow = ( flags & RIDEV_REMOVE ) ? NULL : hWnd;

            RAWINPUTDEVICE rawInputMouses[] =
            {
                { HID_USAGE_PAGE_GENERIC, HID_USAGE_GENERIC_MOUSE, flags, notifyWindow },
                { HID_USAGE_PAGE_CONSUMER, HID_USAGE_CONSUMERCTRL, flags, notifyWindow }
            };
            USHORT rawInputDeviceNumber;
            PRAWINPUTDEVICE pRawInputDevice;
            pRawInputDevice = rawInputMouses;
            rawInputDeviceNumber = _countof( rawInputMouses );

            ::RegisterRawInputDevices( pRawInputDevice, rawInputDeviceNumber, sizeof( RAWINPUTDEVICE ) );
        }

        void OpenRightClickMenu(HWND hWnd)
        {
            HINSTANCE hInstance = ::GetModuleHandle( NULL );
            HMENU menu = ::LoadMenu( hInstance, MAKEINTRESOURCE(IDM_MY_POP_MENU) );
            HMENU popMenu = ::GetSubMenu( menu, 0 );
            POINT cursorPosition = {0};
            ::GetCursorPos( &cursorPosition );
            ::TrackPopupMenu( popMenu, NULL, cursorPosition.x, cursorPosition.y, 0, hWnd, NULL ); 
        }
Popup menus only
Don't forget this function only works for popup menus.