Xearinox
Xearinox

Reputation: 3234

WM_LBUTTONDOWN & WM_LBUTTONUP not received

I created toplevel window, but for unknown reasons my WNDPROC does not receive WM_LBUTTONDOWN/WM_LBUTTONUP nor WM_MOUSEMOVE messages.

Any suggestions?

Relevant code:

WNDCLASSEX wc = {0};
Wc.cbSize = 48;
Wc.cbWndExtra = 80;
Wc.hCursor = LoadCursorW(g_hInstance, MAKEINTRESOURCEW(1002));
Wc.style = CS_GLOBALCLASS | CS_DBLCLKS;
Wc.lpszClassName = Ici[dItemIndex].sInit;
Wc.lpfnWndProc = Ici[dItemIndex].wInit;

RegisterClassExW(&Wc);

g_hRuler1 = CreateWindowExW(WS_EX_TOOLWINDOW,
                            RULER_CONTROL,
                            L"",
                            WS_POPUP|WS_VISIBLE|0x1,
                            100 ,100, 40, RECTHEIGHT(g_rScreen),
                            NULL, NULL, hInst, NULL);

LRESULT WINAPI Ruler_Window(HWND hWindow, UINT uWindow, WPARAM wParam, LPARAM lParam)
{
    if (uWindow == WM_GETMINMAXINFO)
    {
        goto DODEFAULT;
    }

    if (uWindow == WM_NCCREATE)
    {
        g_pGRI = RULER_ALLOCATE();

        RULER_SET_POINTER(hWindow, (LONG_PTR)g_pGRI);

        return 1L;
    }

    g_pGRI = RULER_GET_POINTER(hWindow);

    g_pGRI->hWindow = hWindow;

    switch(uWindow)
    {
    case WM_CREATE:
        {
            return Ruler_OnCreate(wParam, lParam);
        }

    case WM_PAINT:
        {
            return Ruler_OnPaint(wParam, lParam);
        }

    case WM_MOUSEMOVE:
        {
            return Ruler_OnMouseMove(wParam, lParam);
        }

    case WM_DESTROY:
        {
            return Ruler_OnDestroy(wParam, lParam);
        }

    case WM_SETCURSOR:
        {
            return Ruler_OnSetCursor(wParam, lParam);
        }

    case WM_LBUTTONDOWN:
        {
            return Ruler_OnLeftButtonDown(wParam, lParam);
        }

    case WM_LBUTTONUP:
        {
            return Ruler_OnLeftButtonUp(wParam, lParam);
        }

    case GM_SETINDICATORS:
        {
            return Ruler_OnSetIndicators(wParam, lParam);
        }

DODEFAULT:
    return DefWindowProcW(hWindow, uWindow, wParam, lParam);
    }

}

Spy++ messages of window after left button click.

enter image description here

Upvotes: 1

Views: 5503

Answers (2)

icabod
icabod

Reputation: 7074

I think that the problem here is that you are most likely not calling DefWindowProc from your custom wndProc method (Ruler_Window).

Your code structure in your wndProc is a little... interesting.

You handle the messages you are interested in in a switch statement (with the exception of WM_NCCREATE, which is fine), but your switch statement doesn't actually have a default: entry... instead you have created a label called DODEFAULT, which you only reference once - when the message is WM_GETMINMAXINFO you goto DODEFAULT. Ignoring the issue of using a goto here, you basically do not handle any messages other than those listed in your code, and more importantly, you don't pass other messages to the default handler.

A very quick, very simple rewrite of your Ruler_Window method:

LRESULT WINAPI Ruler_Window(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if (uMsg == WM_NCCREATE)
    {
        g_pGRI = RULER_ALLOCATE();
        RULER_SET_POINTER(hWindow, (LONG_PTR)g_pGRI);
        return DefWindowProcW(hWindow, uMsg, wParam, lParam);
    }

    // not sure what g_pGRI is, guessing it's a global?
    // should this actually be passed into the handlers below?
    g_pGRI = RULER_GET_POINTER(hWindow);
    g_pGRI->hWindow = hWindow;

    switch(uMsg)
    {
    case WM_CREATE:
        return Ruler_OnCreate(wParam, lParam);

    case WM_PAINT:
        return Ruler_OnPaint(wParam, lParam);

    case WM_MOUSEMOVE:
        return Ruler_OnMouseMove(wParam, lParam);

    case WM_DESTROY:
        return Ruler_OnDestroy(wParam, lParam);

    case WM_SETCURSOR:
        return Ruler_OnSetCursor(wParam, lParam);

    case WM_LBUTTONDOWN:
        return Ruler_OnLeftButtonDown(wParam, lParam);

    case WM_LBUTTONUP:
        return Ruler_OnLeftButtonUp(wParam, lParam);

    case GM_SETINDICATORS:
        return Ruler_OnSetIndicators(wParam, lParam);

    default:
        break;
    }

    return DefWindowProcW(hWindow, uMsg, wParam, lParam);
}

Note, I also changed the name of the message parameter to be uMsg, as it makes reading the code much easier, IMHO.

Upvotes: 5

Stewart
Stewart

Reputation: 4028

I suspect that the problem is that you are not calling DefWindowProc for WM_NCCREATE and WM_CREATE. This means that the window is never setting up its client areas, so the messages are coming in as WM_NC*.

You should always pass WM_NCCREATE and WM_CREATE on to DefWindowProc.

Upvotes: 3

Related Questions