1

我创建了顶层窗口,但由于未知原因,我的 WNDPROC 没有收到WM_LBUTTONDOWN/WM_LBUTTONUPWM_MOUSEMOVE消息。

有什么建议么?

相关代码:

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++ 消息。

在此处输入图像描述

4

2 回答 2

5

我认为这里的问题是您很可能不会DefWindowProc从您的自定义wndProc方法 ( Ruler_Window) 中调用。

你的代码结构wndProc有点……有趣。

您在 switch 语句中处理您感兴趣的消息(除了WM_NCCREATE,这很好),但您的 switch 语句实际上没有default:条目......相反,您创建了一个名为 的标签DODEFAULT,您只引用一次- 当消息是WM_GETMINMAXINFOgoto DODEFAULT。忽略此处使用 a 的问题goto,您基本上不处理代码中列出的消息以外的任何消息,更重要的是,您不会将其他消息传递给默认处理程序

对您的方法进行非常快速、非常简单的重写Ruler_Window

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);
}

请注意,我还将消息参数的名称更改为uMsg,因为它使阅读代码更容易,恕我直言。

于 2013-08-16T09:16:44.403 回答
3

我怀疑问题在于您没有为 WM_NCCREATE 和 WM_CREATE 调用 DefWindowProc。这意味着窗口永远不会设置其客户区,因此消息以 WM_NC* 的形式传入。

您应该始终将 WM_NCCREATE 和 WM_CREATE 传递给 DefWindowProc。

于 2013-08-15T18:46:48.817 回答