将Win32窗口绘制到文件

时间:2010-08-19 18:26:28

标签: c# .net wpf winapi

在WPF应用程序(C#)中,其中一个元素是Win32 Window,它是通过覆盖HwndHost类创建的。在任何给定时间,WPF中大约有10个Win32窗口实例。一个应该完全渲染(工作正常),另一个9应该只显示预览,而不创建Win32窗口,只是一个位图。

我一直试图找到生成所述位图的方法。尝试了很多不同的事情,但到目前为止还没有真正奏效。我遇到的主要问题是只在窗口可见时调用HwndHost.WndProc。

我可以截取一个可见窗口的截图,将其渲染到内存并创建一个位图。我只是需要一些方法来实现这个窗口不可见。

我的理解仍然很模糊,所以任何见解都会受到赞赏。

4 个答案:

答案 0 :(得分:4)

您可以通过模拟WM_PAINT消息来强制窗口绘制到位图中。您需要设置内存DC并在其中选择目标位图,然后将该DC句柄作为绘图消息中的arg传递。有关详细信息,请参阅MSDN docs

一旦args准备好滚动,请执行SendMessage(HwndHost.Handle,WM_PAINT等)。当该调用返回时,位图应该包含窗口的图像。

请注意,完整绘制整个窗口涉及许多消息。一般模式是:

  1. 使窗口的整个客户区无效。否则,将不会绘制任何内容,因为剪辑rect将为空。
  2. 在内存DC中设置内存位图
  3. 向窗口句柄发送WM_ERASEBKGND消息,传入内存dc句柄
  4. 将WM_PAINT消息发送到窗口句柄,传入内存dc句柄
  5. 窗口的图像现在应该在内存位图中。

    如果您还想捕获目标窗口的边框,窗口框架和窗口标题,则需要模拟非客户端绘制消息:WM_NCPAINT是主要的,不在我的头顶。

    还有一条WM_PRINT消息,据说有助于绘制到用于打印的内存DC,但我在几个版本的Windows之前遇到了麻烦。儿童控制不是自己画等等。

答案 1 :(得分:1)

You should not directly send a WM_PAINT message, as per MSDN spec. 从Windows XP开始,您可能会使用PrintWindow(),可能会在设置了RDW_INTERNALPAINT标志的情况下强制使用RedrawWindow()进行更新。

答案 2 :(得分:0)

研究“双缓冲”的图形技术。一旦你理解了这种技术 - 这并不难 - 你将找到解决问题的方法。在我看来。 : - )

链接:

Win32 Double Buffering

MSDN Double Buffering很多'O链接

WinForms Double Buffering通过Google找到 - 质量未知

答案 3 :(得分:0)

我不知道这在使用WPF的C#中是如何工作的,所以我只是给你一个Windows API透视图,并希望其中一些能引导你找到解决方案。

所有绘图都是在设备上下文(DC)中完成的。当Windows要求您绘制窗口时,它还允许您访问与窗口的可绘制表面相对应的DC。

要在没有窗口的情况下绘制,您需要创建自己的DC,并且由于这些位不会进入窗口,因此您需要在DC中选择一个位图来保存结果。在Windows API中,您将使用CreateCompatibleDCSelectObject。一旦你有了DC,就像正常一样绘制它,然后取消选择位图。