Tom Huntington
Tom Huntington

Reputation: 3425

GetMenuBarInfo() win32 function

I wanted to get the dimensions of a drop-down menu from the menu-bar. According to Microsoft documentation if I pass in OBJID_CLIENT to the idObject parameter of

BOOL GetMenuBarInfo(
  HWND         hwnd,
  LONG         idObject,
  LONG         idItem,
  PMENUBARINFO pmbi
);

I should be able to retrieve the MENUBARINFO structure of

The popup menu associated with the window.


However I don't believe there is a pop-up menu associated with a window. Calling GetMenuBarInfo() with OBJID_CLIENT gives me zeros, calling SetMenu() (on a sub-menu on the menu-bar) gives me an ERROR_INVALID_PARAMETER error code. TrackPopupMenu() is the only documented way to display pop-up menus but it blocks.

Is the documentation wrong?

Upvotes: 1

Views: 697

Answers (3)

Tom Huntington
Tom Huntington

Reputation: 3425

case WM_MENUSELECT:
    {
        HWND myhWnd = FindWindowW(L"#32768", nullptr);       
        GetMenuBarInfo(myhWnd, OBJID_CLIENT, 0, &info);
        printf_rect(info.rcBar);
    }

works. But I wouldn't have known how to get the name of the system menu class without out Drake's answer:

hook the Winproc of system menu class L"#32768".

Upvotes: 2

Drake Wu
Drake Wu

Reputation: 7170

In this case, hWnd needs to specify the window handle of menu bar, and the pop menu is visible.

This is usually used in Windows Hook. sample:

HHOOK hhook;
LRESULT CALLBACK myHookProc(int code, WPARAM wParam, LPARAM lParam)
{
    CWPSTRUCT* lpcwps = (CWPSTRUCT*)lParam;
    BOOL ret = 0;
    if (code == HC_ACTION)
    {
        if (lpcwps->message == MN_GETHMENU)
        {
            MENUBARINFO minfo;
            minfo.cbSize = sizeof(MENUBARINFO);
            ret = GetMenuBarInfo(lpcwps->hwnd, OBJID_CLIENT, 0, &minfo);
            printf_rect(minfo.rcBar);
        }

    }
    return CallNextHookEx(hhook, code, wParam, lParam);
}

And

hhook = SetWindowsHookEx(WH_CALLWNDPROC, (HOOKPROC)myHookProc, hInstance, GetCurrentThreadId());

This will hook the Winproc of system menu class L"#32768", and get the menubar window when the after the pop-up menu has been visable.

Upvotes: 2

Alex Guteniev
Alex Guteniev

Reputation: 13679

TrackPopupMenu() does not block your code from execution. It has message loop inside, this message loop processed popup menu messages and messages of your window.

For example, if your window is being repainted while showing menu caused by TrackPopupMenu(), you are able to find that menu using GetMenuBarInfo from your WM_PAINT handler. Same way with WM_TIMER or other messages, there's even dedicated WM_ENTERMENULOOP message.

Upvotes: 2

Related Questions