等待另一个 Windows 进程重绘其主窗口的可靠方法

Posted

技术标签:

【中文标题】等待另一个 Windows 进程重绘其主窗口的可靠方法【英文标题】:Reliable way to wait for another Windows process to redraw its main window 【发布时间】:2010-07-18 17:03:39 【问题描述】:

我正在将一个窗口(属于另一个进程)移到前面,以便对其进行截图。我可以使用SetForegroundWindow 来执行此操作,但是该函数会立即返回。另一个过程需要不同的时间来重绘其主窗口(这需要它访问数据库),所以我不能确定当我截取屏幕截图时窗口是否已完全呈现。有时我在屏幕截图中得到的只是目标窗口的轮廓,位于之前位于前台的任何窗口之上。

是否有可靠的方法来等待另一个进程的窗口完全绘制?我怀疑没有,但值得一试。也许有一条消息我可以发送到窗口会产生这种效果?

注意:实现语言并不重要,但我需要使用本机 Windows API 的解决方案,直接来自 C/C++ 代码或通过 P/Invoke(例如来自 C# 或 VB.NET) .不幸的是,我不能使用任何 WinForms 函数。

【问题讨论】:

【参考方案1】:

我使用以下策略获得了不错的结果:

    调用PrintWindow将目标窗口渲染为位图并丢弃结果。 调用SetForegroundWindow将目标窗口带到前面(这也会触发重绘,但重绘通常很快,因为同步的WM_PRINTCLIENT已经强制进程分页渲染所需的数据。) 短时间睡眠(10ms) 使用BitBlt截图 恢复目标窗口原来的Z轴顺序

【讨论】:

【参考方案2】:

UpdateWindow 将在窗口的任何部分需要重新绘制时重新绘制窗口,然后返回。

【讨论】:

我还是有同样的问题。 UpdateWindow 在绘画完成之前返回得太早了。 @finnw:我想在UpdateWindow 之后,我会打电话给WaitForInputIdle,看看能不能解决问题。我以前没有在这种情况下使用过WaitForInputIdle,所以我不能保证它会有效,但我猜至少有一个相当不错的机会...... @Jerry Coffin IIRC WaitForInputIdle 仅在进程启动时有效。 这绝对可以。确保您拥有正确的句柄并获得真正的回报。如果窗口在后台线程中查询 dbase 并延迟渲染结果,那么您只能休眠。 @Anders:根据 MSDN:“WaitForInputIdle 可以随时使用,而不仅仅是在应用程序启动期间。” (msdn.microsoft.com/en-us/library/ms687022(VS.85).aspx)。不幸的是,它还说:“但是,WaitForInputIdle 只等待一次进程变为空闲;随后的 WaitForInputIdle 调用立即返回,无论进程是空闲还是忙碌。”

以上是关于等待另一个 Windows 进程重绘其主窗口的可靠方法的主要内容,如果未能解决你的问题,请参考以下文章

在 Windows 中,如何使用 C++ 或 C# 在属于另一个进程的窗口中突出显示文本?

opengl刷新界面时要怎么阻止windows窗口重绘

关于Windows更新窗口内容的问题(作为一个实验,效果很明显)

阻止特定进程的 Windows 错误报告 (DW20.exe) 窗口

如何在窗口中重绘 Qt 窗口或 tabview

窗口重绘