在WindowsFormsHost上使用RenderTargetBitmap

时间:2009-11-18 15:51:13

标签: c# .net wpf winforms

我在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();

关于为什么这可能不起作用以及可能的解决办法的建议?我想这不是真的假设以这种方式工作,但人们真的希望!

2 个答案:

答案 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执行任何操作。有关BitBltGetDC的定义,请查看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");
    }