Bitmap Snapshots of WPF Visuals
Recently I needed to create a bitmap of some WPF controls to be used in another program. Doing a quick search turned up references to the RenderTargetBitmap class in WPF with sample code along the lines of:
RenderTargetBitmap bmp = new RenderTargetBitmap((int)element.Width,
(int)element.Height, 96, 96, PixelFormats.Pbgra32);
bmp.Render(element);
However if the WPF control had a margin then the rendered bitmap had transparent pixels for the margin area. As an example here is a button inside a StackPanel with a margin applied.
And the following is the bitmap that is created via the sample code above:
Doing some more searching turned up the following code which creates a VisualBrush from the target Visual and then renders that into a DrawingVisual and then finally uses RenderTargetBitmap to take a snapshot of the DrawingVisual. Using this approach the margins are ignored and the bitmap only consists of the target WPF control/visual as shown below:
void CreateBitmapFromVisual(Visual target, string filename)
{
if (target == null)
return;
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap rtb = new RenderTargetBitmap((Int32)bounds.Width,
(Int32)bounds.Height, 96, 96, PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(target);
dc.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
}
rtb.Render(dv);
PngBitmapEncoder png = new PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(rtb));
using (Stream stm = File.Create(filename))
{
png.Save(stm);
}
}