我在WindowsFormsHost
中有一组控件,我想捕获当前视图并将其保存为图像,但我只能在图像中看到一些Panel
。
是否可以将WindowsFormsHost用作“Visual”并捕获包装的控件?
参见我的例子:
<WindowsFormsHost x:Name="windowHost">
<wf:Panel Dock="Fill" x:Name="basePanel"/>
</WindowsFormsHost>
如果我要向basePanel
添加一个Button或其他内容,则在使用以下代码导出到PNG时,这将不可见:
RenderTargetBitmap rtb = new RenderTargetBitmap(basePanel.Width,
basePanel.Height, 96, 96, PixelFormats.Pbgra32);
rtb.Render(windowHost);
PngBitmapEncoder pnge = new PngBitmapEncoder();
pnge.Frames.Add(BitmapFrame.Create(rtb));
Stream stream = File.Create("test.jpg");
pnge.Save(stream);
stream.Close();
关于为什么这可能不起作用以及可能的解决办法的建议?我想这不是真的假设以这种方式工作,但人们真的希望!
答案 0 :(得分:6)
WindowsFormsHost
的内容由GDI +呈现,就像在Windows窗体应用程序中一样,因此您不能使用RenderTargetBitmap,因为它不是由WPF呈现的。相反,您应该使用GDI + BitBlt函数,它允许您捕获屏幕上的区域。
请参阅this post以获取示例
更新:这是代码的另一个版本,更新后用于WPF:
using System.Drawing;
...
public static ImageSource Capture(IWin32Window w)
{
IntPtr hwnd = new WindowInteropHelper(w).Handle;
IntPtr hDC = GetDC(hwnd);
if (hDC != IntPtr.Zero)
{
Rectangle rect = GetWindowRectangle(hwnd);
Bitmap bmp = new Bitmap(rect.Width, rect.Height);
using (Graphics destGraphics = Graphics.FromImage(bmp))
{
BitBlt(
destGraphics.GetHdc(),
0,
0,
rect.Width,
rect.Height,
hDC,
0,
0,
TernaryRasterOperations.SRCCOPY);
}
ImageSource img = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
bmp.GetHBitmap(),
IntPtr.Zero,
Int32Rect.Empty,
BitmapSizeOptions.FromEmptyOptions());
return img;
}
return null;
}
只需将您的WindowsFormsHost
控件作为参数传递给Capture
方法,然后对生成的ImageSource
执行任何操作。有关BitBlt
和GetDC
的定义,请查看this website(我在家用计算机上写过,我现在无法访问此处)
答案 1 :(得分:4)
Windows窗体控件也知道如何渲染自身,您不必跳过屏幕捕获箍。看起来像这样:
using (var bmp = new System.Drawing.Bitmap(basePanel.Width, basePanel.Height)) {
basePanel.DrawToBitmap(bmp, new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height));
bmp.Save(@"c:\temp\test.png");
}