【问题标题】:MFC app doesn't seem to receive input messages?MFC 应用程序似乎没有收到输入消息?
【发布时间】:2011-11-18 10:52:03
【问题描述】:

我们有一个不响应任何用户输入的 MFC Visual-C++ 应用程序。

(注意:目前仅在一台机器上知道。该行为偶尔会再次出现,但仅在应用程序运行几天后才会出现!)

当我们通过 Alt-Tab(或任务栏)切换到应用程序时,会重绘该应用程序,但我们不能,例如,通过单击标题栏来激活它的主窗口。 p>


我们已经使用 WinDbg 提取了 4 个转储并检查了活动指令。我们总是在主线程(GUI线程)内的一些重绘代码或类似的东西中。我们确实不是处于模态消息循环中,并且主线程的堆栈总是看起来“OK”。 (大多数/所有工作线程都处于空闲状态,等待某个事件,也没有可疑代码。)


在调查Spy++ 的问题时,我们还看到in this separate question 指定的行为,即我们似乎收到了绘制和激活消息,但没有用户输入被路由到应用程序。当我在屏幕上有应用程序窗口并选择它以显示主窗口的消息时,

它只会显示“通用”“referesh”消息,不会显示其他信息

如果我钻得更深,并选择整个过程的所有消息,

这就是我们所看到的:

该应用显然只在一个隐藏的子窗口 (00CB09F0) 上处理消息,而我们看到的是稳定的 每秒 200 条 WM_PAINT 消息流

通常,此子窗口根本不处理任何消息(Windows 发送消息时刷新 WM_PAINT 等除外)。它通常用作绘图区域,并且通过其父 (010A09B8) 窗口上的 WM_TIMER 消息进行绘图。 (不过,挂起的应用程序上也不会显示此 WM_TIMER 消息。)

进程资源管理器中显示的性能配置文件如下所示(100% 内核时间,或多或少):

【问题讨论】:

    标签: windows winapi visual-c++ mfc window-messages


    【解决方案1】:

    我会说你在那个接收 WM_PAINT 泛洪的窗口中有一个重绘循环。

    如果您在 WM_PAINT 消息的处理过程中直接或间接调用 Invalidate 或类似名称,通常会发生这种情况。

    其他可能性是,由于您说您正在使用计时器来重绘窗口,因此实际绘制所花费的时间比它自己的时间更多,因此消息堆积在队列中。

    另一种可能性是,您正在从与绘制线程不同的线程中使窗口无效。

    无论如何,您应该确保正确调用Invalidate*()(您没有显示代码),而不是来自OnPaint 事件。并且避免调用UpdateWindow(),因为如果不小心调用这个函数会搞砸。

    【讨论】:

    • 多个 Invalidate 调用被压缩为一条 WM_PAINT 消息,因此您永远不会因此而落后。
    • @MarkRansom True,WM_TIMER 也没有。除非他手动发送 WM_PAINTs 而不是调用Invalidate(是的,我已经看到了)。
    • 哦,是的,我也见过。一个很大的禁忌。
    • 感谢您的提示。我应该提到,我们对应用程序进行了 几个 转储,并且没有看到任何可疑代码在运行。
    【解决方案2】:

    当从对话框中抛出异常时,我已经看到了这个问题。 MFC 的 DoModal 函数禁用主程序窗口,然后在对话框返回时重新启用它;异常绕过重新启用部分,主窗口永远保持禁用状态。

    【讨论】:

    • 嗯 ...如果窗口/窗口(MDI!)被禁用​​或不应该通过 Spy++ 检查并检查寡妇的样式标志,不是吗?我们还没有这样做(还)。 (需要等待下次复发。)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    相关资源
    最近更新 更多