C++ 当应用程序菜单具有焦点时,消息循环被阻止

C++ 当应用程序菜单具有焦点时,消息循环被阻止,c++,windows,visual-studio-2008,blocking,C++,Windows,Visual Studio 2008,Blocking,我正在开发一个主要如下所示的应用程序: while (true) { while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } DoSomething(); Sleep(1); } 我注意到,当我单击菜单栏(显示菜单选项)时,DoSomething()不会被调用。

我正在开发一个主要如下所示的应用程序:

while (true)
{
    while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
    {
       TranslateMessage(&Msg);
       DispatchMessage(&Msg);
    }
    DoSomething();
    Sleep(1);
}
我注意到,当我单击菜单栏(显示菜单选项)时,DoSomething()不会被调用。我注意到DispatchMessage调用会阻止messae循环,直到我离开菜单栏

我怎样才能避免这种行为


谢谢

将消息翻译和分派到单独的线程中

只要DoSomething不依赖于发送消息


虽然我可能想了解为什么调度被阻塞;这是预期的正常行为吗?

原因是,当显示应用程序菜单或消息框等内容时,Windows会接管消息处理,并且Windows使用的消息循环不会调用您的
DoSomething()
方法。这可能很难想象,因此我将尝试逐步了解正在发生的事情:

  • 当有人打开你的菜单时,会向你的窗口发送一条消息,告诉它绘制窗口
    DispatchMessage()
    与所有其他消息一样,将消息发送到您的
    WndProc
  • 由于您不处理此消息,因此会将其传递给Windows(因为您的
    WndProc
    很可能会调用
    DefWindowProc
  • 作为默认操作,Windows绘制菜单并启动另一个默认消息循环,该循环不会调用
    DoSomething()
  • 此循环获取发送给应用程序的消息,并通过调用
    WndProc
    将其发送给应用程序,这样应用程序就不会冻结并继续运行(减去
    DoSomething()
    调用)
  • 菜单关闭后,控件将返回到消息循环(只有在此时,
    DispatchMessage()
    调用才会从一开始返回)
换句话说,当显示菜单时,您的消息循环将替换为如下所示的默认循环(例如)

正如您所看到的,它不会调用您的
DoSomething()
方法

若要测试这一点,请尝试在未显示菜单时暂停调试器中的代码,而在未显示菜单时暂停。如果您看到callstack,您将看到当显示菜单时,消息由Windows消息循环处理,而不是由您的消息循环处理


我能想到的唯一解决方法(没有多线程)是启动计时器并通过调用
DoSomething()
来处理
WM\u timer
消息,但这不是一个完美的解决方案(因为我认为您的意图是仅在没有消息要处理时调用
DoSomething()
).

这并不容易,因为窗口消息必须在创建窗口的线程中处理。此外,DoSomething会进行一些opengl渲染并调用swapbuffers,因此opengl渲染可能随时发生,我认为应用程序会崩溃。GetMessage()返回BOOL,但它实际上有一个三态返回值。如果它返回-1(表示错误),那么您的代码片段可能会崩溃或无限循环。在一个
>0
检查中编辑,就像我通常拥有的一样。那些投票否决我的人能告诉我我做错了什么吗?
while (GetMessage(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
}