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

标签 c++ windows visual-studio-2008 blocking

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

while (true)
{
    while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
    {
       TranslateMessage(&Msg);
       DispatchMessage(&Msg);
    }
    DoSomething();
    Sleep(1);
}

我注意到,当我单击菜单栏(显示菜单选项)时,不会调用 DoSomething()。我观察到 DispatchMessage 调用会阻塞消息循环,直到我离开菜单栏!

我怎样才能避免这种行为??

谢谢!

最佳答案

原因是因为当显示应用程序菜单或消息框之类的内容时,Windows 会接管消息处理,而 Windows 使用的消息循环不会调用您的 DoSomething() 方法.这可能很难形象化,所以我将尝试逐步了解正在发生的事情:

  • 当有人打开您的菜单时,会向您的窗口发送一条消息,告诉它绘制窗口。 DispatchMessage() 将消息发送到您的 WndProc,就像所有其他消息一样。
  • 由于您不处理此消息,它被传递给 Windows(因为您的 WndProc 很可能调用 DefWindowProc)
  • 作为默认操作,Windows 绘制菜单并启动另一个默认消息循环它不会调用DoSomething()
  • 此循环获取发往您的应用程序的消息,并通过调用 WndProc 将它们分派(dispatch)给您的应用程序,因此您的应用程序不会卡住并继续运行(减去 DoSomething()调用)。
  • 一旦菜单关闭,控制将返回到您的消息循环(只有此时 DispatchMessage() 调用才会返回)

换句话说,当显示菜单时,您的消息循环将被替换为默认的消息循环,如下所示(例如)

while (GetMessage(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg); 
    DispatchMessage(&msg); 
} 

如您所见,它不会调用您的 DoSomething() 方法。

要对此进行测试,请尝试在没有菜单显示时在调试器中暂停您的代码,而有菜单显示时。如果您看到调用堆栈,您会看到当显示菜单时,消息正在由 Windows 消息循环处理,而不是由您自己处理。

我能想到的唯一解决方法(没有多线程)是如果你启动一个计时器并通过调用 DoSomething() 处理 WM_TIMER 消息,但那不是一个完美的解决方案(因为我认为您的意图是仅在没有消息需要处理时调用 DoSomething())。

关于c++ - 当应用程序菜单具有焦点时,消息循环被阻塞,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1449432/

相关文章:

C++:全局容器未被修改

java - 使 Java Swing 在 Windows 中接受用户输入路径(从资源管理器复制粘贴路径)

visual-studio-2008 - Visual Studio 2008 工具栏莫名其妙地不断移动

c++ - 静态库 - 使用自己的 Qt .so 文件的静态库

c++ - 看起来实际上是无限的 'for' 循环

c++ - 通过 `IShellItem`获取文件大小

php - Apache, PHP, 找不到指定的模块

c# - Visual Studio 2008 - 为什么 vshost.exe 的完整路径限制为 126 个字符?

visual-studio-2008 - "the outputpath property is not set for this project"错误

c++ - Makefile 隐式规则不起作用