首页 > 解决方案 > 如果队列中已经有东西,PeekMessage 是否永远不会生成新的 WM_TIMER 消息,无论过滤器如何?

问题描述

我知道WM_TIMER消息是由Get&动态生成的Peek,基于一些标志“计时器已过,当您准备好发布计时器消息时”。

文档

WM_TIMER 消息是低优先级消息。仅当线程的消息队列中没有其他更高优先级的消息时,GetMessage 和 PeekMessage 函数才发布此消息。

这是否意味着如果我将它与以下过滤器一起使用,PeekMessage它将返回(即没有消息):False

messageFound = PeekMessage(&msg, hwnd, WM_TIMER, WM_TIMER, PM_REMOVE)

如果队列中有任何更高优先级的消息;即使是那些与过滤器不匹配的?因此,由于存在(不匹配的)高优先级消息,这两个队列都会返回 false

WM_NOTIFY                        or        WM_NOTIFY
--Flag to autogenerate timer--             WM_TIMER

WM_SYS­TIMER产生影响,因为它WM_TIMER

还是仅仅意味着如果我没有过滤器,那么如果队列中有其他消息,WM_TIMER则不会创建新的自动生成的消息,但是已经存在的任何消息(例如 Peek + PM_NOREMOVE)都会像普通消息一样表现?(即 Peek 现在只返回先发布的内容)


If highPriorityMessagesExist() Then
    Return anyOfThemMatchTheFilter()
Else 
    If !lowPriorityMessagesExist()
        tryGenerateSomeFromFlags()

    If lowPriorityMessagesExist()
        Return anyOfThemMatchTheFilter()
    Else
        Return False

对比

If anyMessagesMatchTheFilter()
    Return True
Else
    tryGenerateSomeFromFlags()
Return anyMessagesMatchTheFilter()

标签: winapitimermessage

解决方案


如果过滤范围内有高优先级的消息,则不会发生 WM_TIMER 消息生成。但是,如果队列中有高优先级的消息,但它们被 GetMessage 或 PeekMessage 的 wMsgFilterMin 和 wMsgFilterMax 参数过滤掉,仍然会生成 WM_TIMER 消息。

换句话说,这个程序生成调试输出:

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    SetTimer(NULL, 101, 500, NULL);

    auto start = GetTickCount();
    while (GetTickCount() - start < 4000) {
        MSG msg;
        PostMessage(NULL, WM_NOTIFY, 0, 0);
        GetMessage(&msg, NULL, WM_TIMER, WM_TIMER);
        if (msg.message == WM_TIMER)
            OutputDebugStringA("WM_TIMER\n");
    }

    return 0;
}

但以下程序不会生成调试输出,因为 WM_NOTIFY 现在在过滤器范围内:

int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
                     _In_opt_ HINSTANCE hPrevInstance,
                     _In_ LPWSTR    lpCmdLine,
                     _In_ int       nCmdShow)
{
    SetTimer(NULL, 101, 500, NULL);

    auto start = GetTickCount();
    while (GetTickCount() - start < 4000) {
        MSG msg;
        PostMessage(NULL, WM_NOTIFY, 0, 0);
        GetMessage(&msg, NULL, WM_NOTIFY, WM_TIMER);
        if (msg.message == WM_TIMER)
            OutputDebugStringA("WM_TIMER\n");
    }

    return 0;
}

推荐阅读