I have a set of controls inside a WindowsFormsHost
and I would like to capture the current view and just save it as an image, I however only get some Panel
visible in the Image.
Is it possible to use the WindowsFormsHost as a "Visual" and capture the wrapped controls?
See my example:
<WindowsFormsHost x:Name="windowHost">
<wf:Panel Dock="Fill" x:Name="basePanel"/>
</WindowsFormsHost>
If i were to add a Button or whatever to the basePanel
this wouldn't be visible when exporting to a PNG with the following code:
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();
Suggestions on why this might not work and maybe a possible work-around? I guess it's not really suppose to work this way, but one could really hope!
The content of the WindowsFormsHost
is rendered by GDI+, like in a Windows Forms application, so you can't use RenderTargetBitmap for that since it is not rendered by WPF. Instead, you should use the GDI+ BitBlt function, which allows you to make a capture of an area on the screen.
See this post for an example
UPDATE: here's another version of the code, updated for use with 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;
}
Just call pass your WindowsFormsHost
control as a parameter to the Capture
method, and do whatever you like with the resulting ImageSource
. For the definitions of BitBlt
and GetDC
, have a look at this website (I wrote that on my home computer, which I can't access from where I am now)
A Windows Forms control also knows how to render itself, you don't have to jump through the screen capture hoop. Make it look like this:
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");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With