Get a bitmap image from a Control view
I would like to "开发者_Python百科copy to clipboard" what a Control
of my WPF
app draws on the screen.
Therefore, I need to build a bitmap image from my Control current display.
Is there an easy way to do that ?
Thanks in advance.
I wouldn't call it easy...but the key component is the RenderTargetBitmap, which you can use as follows:
RenderTargetBitmap rtb = new RenderTargetBitmap((int)control.ActualWidth, (int)control.ActualHeight, 96, 96, PixelFormats.Pbgra32);
rtb.Render(control);
Well, that part is easy, now the RTB has the pixels stored internally...but your next step would be putting that in a useful format to place it on the clipboard, and figuring that out can be messy...there are a lot of image related classes that all interact one or another.
Here's what we use to create a System.Drawing.Image, which i think you should be able to put on the clipboard.
PngBitmapEncoder png = new PngBitmapEncoder();
png.Frames.Add(BitmapFrame.Create(rtb));
MemoryStream stream = new MemoryStream();
png.Save(stream);
Image image = Image.FromStream(stream);
System.Drawing.Image (a forms image) cannot interact directly with the RenderTargetBitmap (a WPF class), so we use a MemoryStream to convert it.
If the control you are trying to create a bitmap from is inside a StackPanel
it won't work, you will just get an empty image.
Jaime Rodriguez has a good piece of code to get around this on his blog:
private static BitmapSource CaptureScreen(Visual target, double dpiX, double dpiY)
{
if (target == null)
{
return null;
}
Rect bounds = VisualTreeHelper.GetDescendantBounds(target);
RenderTargetBitmap rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
(int)(bounds.Height * dpiY / 96.0),
dpiX,
dpiY,
PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext ctx = dv.RenderOpen())
{
VisualBrush vb = new VisualBrush(target);
ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
}
rtb.Render(dv);
return rtb;
}
This goes in your codebehind: (Or pass in the window.)
Not mine, but a mishmash of mine, and googling. Works in .Net 5 and WPF
public void RenderThisWindow(string fullPngPath)
{
Image myImage = new Image();
DrawingVisual drawingVisual = new DrawingVisual();
RenderTargetBitmap bmp = new RenderTargetBitmap((int)Width, (int)Height, 120, 96, PixelFormats.Pbgra32);
bmp.Render(this);
myImage.Source = bmp;
SaveToPng(this, fullPngPath);
}
private void SaveToPng(FrameworkElement visual, string fileName)
{
var encoder = new PngBitmapEncoder();
SaveUsingEncoder(visual, fileName, encoder);
}
private void SaveUsingEncoder(FrameworkElement visual, string fileName, BitmapEncoder encoder)
{
RenderTargetBitmap bitmap = new RenderTargetBitmap((int)visual.Width, (int)visual.Width, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(visual);
BitmapFrame frame = BitmapFrame.Create(bitmap);
encoder.Frames.Add(frame);
using (var stream = File.Create(fileName))
{
encoder.Save(stream);
}
}
精彩评论