检测鼠标悬停在按钮上?

Detect Mouse Hover Over Button?

我有一个自己绘制的按钮,当鼠标悬停在它上面时,我想突出显示它。这是简化的代码,似乎不起作用:

case WM_DRAWITEM:
     LPDRAWITEMSTRUCT  pDraw = (LPDRAWITEMSTRUCT)lParam;
     if(pDraw->itemState == ODS_HOTLIGHT)  DrawButton(pDraw->hDC, HIcolor);
     else                                  DrawButton(pDraw->hDC, normcolor);
     return 0;

DrawButton是绘制按钮的自定义函数。这个函数的第二个参数是按钮的原色。该函数可以轻松绘制按钮。检测“项目状态”的问题。

我也尝试过使用 if(pDraw->itemState & ODS_HOTLIGHT)。那也不行。

显然,我遗漏了一些东西。在我的搜索中,我遇到了很多答案。但是,其中 none 是在 C++ 中。

ODS_HOTLIGHT 值的 the description 所述:

ODS_HOTLIGHT: The item is being hot-tracked, that is, the item will be highlighted when the mouse is on the item.

因此,我想您需要先使用 TrackMouseEvent 功能才能收到此消息。

ODS_HOTLIGHT 不能被按钮使用。参见 What states are possible in a DRAWITEMSTRUCT structure?

您可以使用 subclassing, and then use TrackMouseEvent to get the event in SUBCLASSPROC.

LRESULT CALLBACK Subclassproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
    if (uMsg == WM_MOUSEMOVE)
    {
        TRACKMOUSEEVENT ev = {};
        ev.cbSize = sizeof(TRACKMOUSEEVENT);
        ev.dwFlags = TME_HOVER | TME_LEAVE;
        ev.hwndTrack = hWnd;
        ev.dwHoverTime = HOVER_DEFAULT;
        TrackMouseEvent(&ev);
    }
    else if (uMsg == WM_MOUSEHOVER)
    {
        RECT rc = {};
        GetClientRect(hWnd, &rc);
        HDC hdc = GetDC(hWnd);
        SetDCBrushColor(hdc, RGB(255, 0, 0));

        SelectObject(hdc, GetStockObject(DC_BRUSH));

        RoundRect(hdc, rc.left, rc.top,
            rc.right, rc.bottom, 0, 0);
    }
    else if (uMsg == WM_MOUSELEAVE)
    {
        RECT rc = {};
        GetClientRect(hWnd, &rc);
        HDC hdc = GetDC(hWnd);
        SetDCBrushColor(hdc, RGB(0, 255, 0));

        SelectObject(hdc, GetStockObject(DC_BRUSH));

        RoundRect(hdc, rc.left, rc.top,
            rc.right, rc.bottom, 0, 0);
        TRACKMOUSEEVENT ev = {};
        ev.cbSize = sizeof(TRACKMOUSEEVENT);
        ev.dwFlags = TME_HOVER | TME_LEAVE | TME_CANCEL;
        ev.hwndTrack = hWnd;
        ev.dwHoverTime = HOVER_DEFAULT;
        TrackMouseEvent(&ev);
    }
    return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}


    ...
    HWND hButton = CreateWindow(L"BUTTON", L"", WS_CHILD | WS_VISIBLE |
        BS_OWNERDRAW, 10, 10, 60, 30, hWnd,
        (HMENU)10001, hInst, NULL);

    SetWindowSubclass(hButton, Subclassproc, 101, 0);