2011-11-18 76 views
1

我们有一个MFC Visual-C++应用程序不会对任何用户输入做出反应。MFC应用程序似乎没有收到输入消息?

(注:!目前只知道一台机器上的行为偶尔会复发,但只有在应用程序已经运行了数天)

应用重绘,当我们通过切换到它Alt-Tab(或任务栏),但我们不能通过点击标题栏来激活它的主窗口。


我们已经用WinDbg拉出4个转储并检查了活动指令。我们总是在一些重绘代码中,或者在主线程(GUI线程)内部。我们在模态消息循环中肯定是而不是,并且主线程的堆栈始终显示为“OK”。 (大多数/所有的工作线程都空闲,等待某个事件,没有发现可疑代码有两种。)


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

App Main Window

它只会显示“通用”,“referesh”的消息,并没有别的

Messages for the main Window

如果我更深入的分析,并选择了整个过程的所有消息,

Windows of same process setting

这就是我们看到:

200 WM_PAINT messages per second

该应用显然在一个隐藏的子窗口(00CB09F0)只处理消息,并且我们看到的有每秒200 WM_PAINT消息的恒定流

通常这个子窗口根本不处理任何消息(除了Windows发送它们时刷新WM_PAINT等)。它通常用作绘图区域,并通过它的父级(010A09B8)窗口上的WM_TIMER消息进行绘图。 (未在悬挂应用中显示该消息WM_TIMER或者虽然。)

如过程资源管理器中示出的性能曲线看起来像这样(100%内核的时间,更多或更少):

Process Explorer App Performance Graph

回答

0

我想说,你有一个重绘循环在那个接收WM_PAINT洪水的窗口。

如果您直接或间接地调用Invalidate或类似处理WM_PAINT消息,通常会发生这种情况。

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

还有一种可能性是,您正在使窗口与创建绘画的窗口不同,从而使窗口无效。

无论如何,您应该确保您正确呼叫Invalidate*()(您没有显示任何代码),并且从来没有从OnPaint事件中调用。并且避免调用UpdateWindow(),因为如果调用该函数,可能会让事情变得无关紧要。

+0

多个Invalidate调用会压缩为单个WM_PAINT消息,因此您永远不会落后于此。 –

+0

@MarkRansom True,WM_TIMER也不会。除非他手动发送WM_PAINT而不是调用'Invalidate'(是的,我已经看到了)。 – rodrigo

+0

哦,是的,我也看到了。一个很大的禁忌。 –

0

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

+0

嗯......如果窗口/窗口(MDI!)被禁用​​或不应该通过Spy ++检查并检查窗口的样式标志,不是吗?我们还没有这样做(还)。 (需要等待下一次再次发生。) –