C# 将Win32窗口绘制为文件

C# 将Win32窗口绘制为文件,c#,.net,wpf,winapi,C#,.net,Wpf,Winapi,在WPF应用程序C中,其中一个元素是Win32 Window,它是通过重写HwndHost类创建的。在任何给定时间,WPF中大约有10个Win32窗口实例。其中一个应该完全渲染工作正常,另外9个应该只显示预览,而不创建Win32窗口,只显示位图 我一直在试图找到生成上述位图的方法。尝试了很多不同的方法,但到目前为止没有任何效果。我遇到的主要问题是,仅当窗口可见时才会调用HwndHost.WndProc 我可以拍摄一个可视窗口的屏幕截图,将其渲染到内存中,然后创建一个位图。。我只需要在窗口不可见的

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

我一直在试图找到生成上述位图的方法。尝试了很多不同的方法,但到目前为止没有任何效果。我遇到的主要问题是,仅当窗口可见时才会调用HwndHost.WndProc

我可以拍摄一个可视窗口的屏幕截图,将其渲染到内存中,然后创建一个位图。。我只需要在窗口不可见的情况下采取一些措施


我的理解仍然很模糊,因此任何见解都值得赞赏。

研究双缓冲的图形技术。一旦你了解了这项技术——这并不难——你就会找到解决问题的办法。在我看来-

链接:

Lots'O链接


通过Google找到-未知质量

查看双缓冲的图形技术。一旦你了解了这项技术——这并不难——你就会找到解决问题的办法。在我看来-

链接:

Lots'O链接


通过Google找到-未知质量

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

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


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

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

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


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

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

参数准备就绪后,执行SendMessageHwndHost.Handle、WM_PAINT等操作。当调用返回时,位图应包含窗口的图像

请注意,完全绘制整个窗口涉及到许多消息。一般情况是:

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

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


还有一个WM_打印消息,据说它有助于将数据写入指定用于打印的内存DC,但我在几个版本的Windows之前遇到过麻烦。子控件本身不绘制等。

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

参数准备就绪后,执行SendMessageHwndHost.Handle、WM_PAINT等操作。当调用返回时,位图应包含窗口的图像

请注意,完全绘制整个窗口涉及到许多消息。一般情况是:

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

如果还希望捕获目标窗口的边框、窗口边框和窗口标题,则需要 模拟非客户端绘制消息:WM_NCPAINT是主要的一个,在我的头顶上

还有一个WM_打印消息,据说它有助于将数据写入指定用于打印的内存DC,但我在几个版本的Windows之前遇到过麻烦。子控件本身不绘制等。

您可以从Windows XP开始使用,可能会使用RDW_INTERNALPAINT标志集调用强制更新。


您可以从Windows XP开始使用,可能会使用RDW_INTERNALPAINT标志集强制调用更新。

您的意思是只有当窗口在屏幕上可见时,或者只有在窗口至少在屏幕上显示一次后,才会调用hwnhost.WndProc?很可能直到第一次显示窗口时才创建窗口句柄。如果窗口或其父窗口在显示后被隐藏或最小化,您仍应在wndproc中获取消息,直到窗口第一次显示在屏幕上。是否可以在显示此窗口之前将其绘制到内存中?或者,一个解决办法可能是在一个新窗口中生成Show;隐藏然后试着画画?请在标签中留下像C这样的标签,并将它们放在你的标题之外。它是多余的。是的,您可以在窗口句柄实际显示之前强制创建它。访问窗口句柄属性应该足以强制创建句柄—这是一种按需模式。尝试从HwndHost读取。在开始屏幕截图运行之前处理。通过设置创建内存DC所需的消息参数,模拟WM_PAINT消息,其中包含位图并包含在WM_PAINT参数中。SendMessageHwndHost.Handle、WM_PAINT等您是说只有当窗口在屏幕上可见时,或者只有在窗口至少在屏幕上显示一次后,才会调用HwndHost.WndProc吗?很可能直到第一次显示窗口时才创建窗口句柄。如果窗口或其父窗口在显示后被隐藏或最小化,您仍应在wndproc中获取消息,直到窗口第一次显示在屏幕上。是否可以在显示此窗口之前将其绘制到内存中?或者,一个解决办法可能是在一个新窗口中生成Show;隐藏然后试着画画?请在标签中留下像C这样的标签,并将它们放在你的标题之外。它是多余的。是的,您可以在窗口句柄实际显示之前强制创建它。访问窗口句柄属性应该足以强制创建句柄—这是一种按需模式。尝试从HwndHost读取。在开始屏幕截图运行之前处理。通过设置创建内存DC所需的消息参数,模拟WM_PAINT消息,其中包含位图并包含在WM_PAINT参数中。谢谢,这是我昨晚开始往的方向。现在读到这篇文章,就更清楚了。非常详细,非常感谢!谢谢,这是我昨晚开始往的方向。现在读到这篇文章,就更清楚了。非常详细,非常感谢!