首页 > 解决方案 > How can I open and close a popup menu when I click on a window in win32 api?

问题描述

I made a little window with the win32 api and want to open a popup menu when I click on the window. When I click on it again I want to close the menu if it's still open.

I open the menu on WM_LBUTTONUP, because I want to drag the window on WM_LBUTTONDOWN.

I know when the menu appears or disappears by WM_ENTERMENULOOP and WM_EXITMENULOOP.

I know how to close the menu programmatically, but unfortunately I don't know how to decide whether the menu is open or closed on WM_LBUTTONUP. The problem is that the menu gets automatically closed on WM_LBUTTONDOWN and that's why I can't save the current state of the menu.

It would be great if someone has a hint how to solve this problem.

Additional information:

标签: c++windowswinapipopupmenu

解决方案


这是使用 WindowsHooks 进行鼠标事件的解决方案您必须在窗口客户区域内捕获鼠标按下事件并跳过下一个鼠标按下事件

在全球范围内

static HHOOK hMouseHook = 0;
static HWND hMainWindow = 0;
static int nSkipClick = 0;

LRESULT CALLBACK MouseProc(_In_ int    nCode, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
    if (nCode < 0)
        return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
    if (wParam == WM_LBUTTONDOWN) {
        MOUSEHOOKSTRUCT* p = (MOUSEHOOKSTRUCT*)lParam;
        if (WindowFromPoint(p->pt) == hMainWindow) {
            POINT pt = p->pt;
            ScreenToClient(hMainWindow, &pt);
            RECT rct;
            GetClientRect(hMainWindow, &rct);
            if (PtInRect(&rct, pt))nSkipClick = 1;
        }
    }
    return CallNextHookEx(hMouseHook, nCode, wParam, lParam);
}

在 WndProc 中

case WM_LBUTTONUP: 
    if (nSkipClick == 0) { // menu not shown before
        hMouseHook = SetWindowsHookEx(WH_MOUSE, &MouseProc, NULL, GetCurrentThreadId());
        hMainWindow = hWnd;
        HMENU hPopupMenu = CreatePopupMenu();
        InsertMenuW(hPopupMenu, 0, MF_BYPOSITION | MF_STRING, ID_ITEM_A, L"ItemA");
        SetForegroundWindow(hWnd);
        RECT wndRect;
        GetWindowRect(hWnd, &wndRect);
        TrackPopupMenu(hPopupMenu, TPM_BOTTOMALIGN | TPM_LEFTALIGN, wndRect.left, wndRect.top, 0, hWnd, NULL);
        UnhookWindowsHookEx(hMouseHook);
        hMouseHook = 0;
    }
    else {
        nSkipClick = 0;
    }
break;

我希望这是你想做的。


推荐阅读