dispatchmessage 函数在 PostMessage 时没有执行 WM_TIMER 消息

dispatchmessage function didn't execute WM_TIMER message when PostMessage

最近在学习win32 并使用 PostMessage 函数。

我发现棘手的事情是当将 WM_TIMER 消息发布到 window 消息队列时,window 没有收到任何消息。 如果只在我将 lparam 设置为 0 时接收,否则根本不工作 这里的代码。 我还用 sendmessage 进行了测试,这两种方式都很好。

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
    switch (msg)
    {
        case WM_CREATE:
        {
            //PostMessage(hWnd, WM_TIMER, 0, 0); // receive msg
            PostMessage(hWnd, WM_TIMER, 0, 1); // not receiving
        }
        return 0;
        case WM_TIMER:
        {
            switch (wparam)
            {
                case 0:
                {
                    HDC dc = GetDC(hWnd);

                    Ellipse(dc, 70, 70, 120, 120);
                    ReleaseDC(hWnd, dc);
                }
                break;
            }
            return 0;
        }
    }
    return DefWindowProc(hWnd, msg, wparam, lparam);
}

如果有人解释为什么会这样,那就太好了。 只是希望我遗漏了一些 windows 处理系统的基本概念。

根据 WM_TIMER 文档:

lParam [in]

A pointer to an application-defined callback function that was passed to the SetTimer function when the timer was installed.

因此,当您使用 PostMessage(hWnd, WM_TIMER, 0, 0) 时,您将 0(作为空指针)传递给 lParam

根据 SetTimer 文档:

A pointer to the function to be notified when the time-out value elapses. For more information about the function, see TimerProc. If lpTimerFunc is NULL, the system posts a WM_TIMER message to the application queue. The hwnd member of the message's MSG structure contains the value of the hWnd parameter.

这意味着当 DispatchMessage() 看到 WM_TIMER 消息的 lParam 设置为 0 时,它只会将消息 as-is 传递给 window hWnd.

指定的 window 的消息过程

但是,当您改用 PostMessage(hWnd, WM_TIMER, 0, 1); 时,您将 1 作为 lParam 传递,因此它被视为指向计时器回调函数的指针。这意味着当 DispatchMessage() 看到 WM_TIMER 消息 lParam 设置为 non-zero 时,它不会将消息传递给 [=19] 的 window 消息过程=],它会尝试实际调用 lParam 指向的函数,这在这种情况下显然是非法的。系统无法通过这个无效指针调用函数。

根据 DispatchMessage() 文档:

The MSG structure must contain valid message values. If the lpmsg parameter points to a WM_TIMER message and the lParam parameter of the WM_TIMER message is not NULL, lParam points to a function that is called instead of the window procedure.