[英]How to render a WPF Hwnd with Graphics Object
之后,RenderTargetBitmap太慢了。 我尝试了另一种方法。 不幸的是,我的尝试没有成功。 希望你们中的一些人能弄清楚为什么此代码不起作用。
var myPopup = new Popup();
var child = new Grid() { Background = new VisualBrush(myVisual)};
myPopup.StaysOpen = false;
myPopup.Child = child;
myPopup.IsOpen = false;
myPopup.Opened += (sender, args) =>
{
var source = ((HwndSource)PresentationSource.FromVisual(myPopup.Child));
var image = new Bitmap(1000,1000);
using (Graphics gr = Graphics.FromHwnd(source.Handle))
{
var ptr = gr.GetHdc();
using (Graphics g = Graphics.FromHdc(ptr))
{
g.DrawImage(image, new System.Drawing.Point(0, 0));
}
gr.ReleaseHdc(ptr);
}
//The image is just black...
image.Save("test.png");
myPopup.IsOpen = false;
};
myPopup.IsOpen = true;
恐怕您的代码无法正常工作。 实际上,您是将一个空图像复制到Graphics
,然后将该图像保存到文件。 因此该文件为空。
如果您不想使用RenderTargetBitmap ,则需要使用BitBlt函数。
让我们来看看如何做。 首先,让我们创建一个帮助程序类,该类管理从Visual到Bitmap的转换:
public static class VisualToBitmapConverter
{
private enum TernaryRasterOperations : uint
{
SRCCOPY = 0x00CC0020,
SRCPAINT = 0x00EE0086,
SRCAND = 0x008800C6,
SRCINVERT = 0x00660046,
SRCERASE = 0x00440328,
NOTSRCCOPY = 0x00330008,
NOTSRCERASE = 0x001100A6,
MERGECOPY = 0x00C000CA,
MERGEPAINT = 0x00BB0226,
PATCOPY = 0x00F00021,
PATPAINT = 0x00FB0A09,
PATINVERT = 0x005A0049,
DSTINVERT = 0x00550009,
BLACKNESS = 0x00000042,
WHITENESS = 0x00FF0062,
CAPTUREBLT = 0x40000000
}
[DllImport("gdi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool BitBlt(IntPtr hdc, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, TernaryRasterOperations dwRop);
public static Bitmap GetBitmap(Visual visual, int width, int height)
{
IntPtr source;
IntPtr destination;
Bitmap bitmap = new Bitmap(width, height);
HwndSource hwndSource = (HwndSource)PresentationSource.FromVisual(visual);
using (Graphics graphicsFromVisual = Graphics.FromHwnd(hwndSource.Handle))
{
using (Graphics graphicsFromImage = Graphics.FromImage(bitmap))
{
source = graphicsFromVisual.GetHdc();
destination = graphicsFromImage.GetHdc();
BitBlt(destination, 0, 0, bitmap.Width, bitmap.Height, source, 0, 0, TernaryRasterOperations.SRCCOPY);
graphicsFromVisual.ReleaseHdc(source);
graphicsFromImage.ReleaseHdc(destination);
}
}
return bitmap;
}
}
现在我们可以编写一个简单的XAML来测试助手类:
<Window x:Class="WpfApplication1.MainWindow" Name="win"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="400">
<StackPanel>
<Border BorderBrush="DarkGray" BorderThickness="4" CornerRadius="4"
Background="LightGray" Padding="6" Name="border">
<Label Content="Copy me to a bitmap file, please" FontSize="20" Foreground="Green"
FontStyle="Italic" />
</Border>
<Button Content="Save to file" Margin="20" HorizontalAlignment="Center"
Click="Button_Click" />
</StackPanel>
</Window>
后面有代码:
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Bitmap image = VisualToBitmapConverter.GetBitmap(border,
(int)border.ActualWidth, (int)border.ActualHeight);
image.Save(@"C:\YourPath\test.png");
}
}
}
如果单击该按钮,将发现Border及其内容已复制到Bitmap文件中。 我希望这种方法的速度适合您的目的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.