首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >无法删除WM_TIMER消息

问无法删除WM_TIMER消息
EN

Stack Overflow用户
提问于 2016-04-15 16:03:06
回答 2查看 677关注 0票数 0

我的代码出了问题,几个小时后,我似乎想不出.

问题:我试图每十秒钟连接一台服务器。当计时器第一次过去时,回调函数被调用得很好,但是它会立即被一次又一次地调用(不需要等待10秒),并且会一次又一次地被调用,就好像计时器消息没有从队列中移除一样。有人能帮忙吗?

定时器设置在这里:

代码语言:javascript
复制
SConnect::SConnect()
{
    hSimConnect = NULL;
    Attempt();
    SetTimer(hMainWindow, reinterpret_cast<UINT_PTR>(this), 10000, (TIMERPROC)TimerProc);
}

(仅)应用程序消息循环如下:

代码语言:javascript
复制
    while (true)
    {
        PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
        if (msg.message == WM_QUIT)
            break;

        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        //UPDATES
        pSCObj->Update();
        manager.Update();
        Sleep(50);
    }

计时器回调函数在这里:

代码语言:javascript
复制
void CALLBACK SConnect::TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime){
    SConnect *pSC = reinterpret_cast<SConnect *>(idEvent);
    MSG wMsg;

    if (!pSC->connected)
    pSC->Attempt();
    else{
        pSC->connected = false;
    }
}

我真的很感激任何帮助..。如果你需要更多信息请告诉我..。

真的,法利

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-04-15 16:32:22

我认为这是因为您在消息循环中调用PeekMessage()而不是GetMessage()。

如果队列中没有消息,PeekMessage()将返回FALSE。我不知道PeekMessage()的实现是什么,但是如果队列中没有消息,我可以看到它只保留msg参数的内容。这意味着当PeekMessage()返回FALSE时,msg将在队列中包含前面的消息。然后,msg被盲目地传递给DispatchMessage(),后者将尽职尽责地将其传递给窗口的窗口过程。因此,只要WM_TIMER消息是最后处理的消息,就会调用您的计时器回调,直到将另一条消息添加到队列中为止。

您可以通过使用更传统的消息循环来修复这个问题:

代码语言:javascript
复制
BOOL bRet;

while( (bRet = GetMessage( &msg, nullptr, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }

    pSCObj->Update();
    manager.Update();
}

(消息循环改编自GetMessage()文档中的示例。)

由于GetMessage()将被阻塞,直到队列中有消息,所以您不需要调用Sleep(),并且当没有任何事情可做时,您的进程将不使用任何CPU。

票数 2
EN

Stack Overflow用户

发布于 2016-04-15 21:20:06

问题是没有检查PeekMessage()的返回值。在每个循环中,如果没有新消息,PeekMessage将msg的内容保持不变,只需再次发送。

只有当PeekMessage()返回true时才发送消息,解决了这个问题:

代码语言:javascript
复制
    while (true)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
            if (msg.message == WM_QUIT)
                break;    

            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }

        //UPDATES
        pSCObj->Update();
        manager.Update();
        Sleep(50);
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36651902

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档