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);
}