Winapi dispatchmessage函数没有';发送后消息时不执行WM_定时器消息

Winapi dispatchmessage函数没有';发送后消息时不执行WM_定时器消息,winapi,message-queue,message,postmessage,Winapi,Message Queue,Message,Postmessage,这些天我在学习win32 并使用PostMessage函数 我发现一件棘手的事情是,当将WM_定时器消息发布到窗口消息队列中时,窗口并没有收到任何消息。 如果只在我将lparam设置为0时接收,否则根本不工作 代码在这里。 我还用sendmessage进行了测试,这两种方法都很好 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wparam, LPARAM lparam) { switch (msg) {

这些天我在学习win32 并使用PostMessage函数

我发现一件棘手的事情是,当将WM_定时器消息发布到窗口消息队列中时,窗口并没有收到任何消息。 如果只在我将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处理系统的基本概念。

根据文档:

lParam[in]

指向应用程序定义的回调函数的指针,该回调函数在安装计时器时传递给
SetTimer
函数

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

根据文件:

指向超时值过期时要通知的函数的指针。有关该函数的更多信息,请参阅TimerProc如果
lpTimerFunc
NULL
,系统将WM\u定时器消息发布到应用程序队列。
消息的
MSG
结构的
hwnd
成员包含
hwnd
参数的值

这意味着当
DispatchMessage()
看到
WM_TIMER
消息且其
lParam
设置为0时,它将按原样将消息传递到
hWnd
指定的窗口的窗口消息过程

但是,当您使用
PostMessage时(hWnd,WM_TIMER,0,1)lParam
传递,因此它被视为指向计时器回调函数的指针。这意味着当
DispatchMessage()
看到
WM_TIMER
消息且其
lParam
设置为非零时,它将不会将消息传递到
hWnd
的窗口消息过程,而是尝试实际调用
lParam
指向的函数,这在这种情况下显然是非法的。系统无法通过此无效指针调用函数

根据文件:

MSG
结构必须包含有效的消息值。如果
lpmsg
参数指向
WM\u TIMER
消息,并且
WM\u TIMER
消息的
lParam
参数不是
NULL
,则
lParam
指向调用的函数,而不是窗口过程


你为什么要发布
WM\u TIMER
消息?您应该调用
SetTimer
,系统会将这些消息发布到您的窗口过程中。事实上,DispatchMessage()会以不同的方式对待它,并且不会调用WndProc。注意,在GetMessage()调用之后,您确实在消息循环中看到了此消息。但这就是它的结尾,如果它对无效的函数指针大喊大叫,那就太好了。它没有。@HansPassant——有趣的是,如果您将其更改为
sendmages
,它就可以正常工作。只是尝试了一下。根据设计,SendMessage()直接调用WndProc,因此不使用DispatchMessage()。GetMessage()仅检索已发布的消息。WM_TIMER通常都是发布的,从不发送。不清楚您是如何得出结论的,即不可能发布
WM_TIMER
消息的。引用的文档并不是这么说的。@I鉴于我的表达式问题,我已经修改了回复,无论如何,我建议使用SetTimer.Great。现在它不再回答被问到的问题了。@I尽管我错了,但我错读了这个问题,我已经修改了我的回答。那没用。它解释了既不理解消息也无法访问源代码的人可能猜到的内容。系统不会看到队列中是否有
WM_TIMER
,如果有,则读取其参数,然后决定在哪里传递。为了得出这个结论,你必须忽略大量的事实。