【发布时间】:2010-03-26 10:11:13
【问题描述】:
我想将Control 的WPF 应用程序在屏幕上绘制的内容“复制到剪贴板”。
因此,我需要从我的 Control 当前显示中构建一个位图图像。
有没有简单的方法可以做到这一点?
提前致谢。
【问题讨论】:
-
这个问题/答案也帮助了我:stackoverflow.com/questions/2557183/…
标签: wpf
我想将Control 的WPF 应用程序在屏幕上绘制的内容“复制到剪贴板”。
因此,我需要从我的 Control 当前显示中构建一个位图图像。
有没有简单的方法可以做到这一点?
提前致谢。
【问题讨论】:
标签: wpf
我认为这并不容易......但关键组件是 RenderTargetBitmap,您可以按如下方式使用它:
RenderTargetBitmap rtb = new RenderTargetBitmap((int)control.ActualWidth, (int)control.ActualHeight, 96, 96, PixelFormats.Pbgra32);
rtb.Render(control);
嗯,这部分很简单,现在 RTB 已将像素存储在内部...但您的下一步是将其以有用的格式放置在剪贴板上,然后弄清楚可能会很麻烦...有很多与图像相关的类都相互交互。
这是我们用来创建 System.Drawing.Image 的内容,我认为您应该可以将其放在剪贴板上。
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(表单图像)无法直接与 RenderTargetBitmap(WPF 类)交互,因此我们使用 MemoryStream 对其进行转换。
【讨论】:
如果您尝试从中创建位图的控件位于 StackPanel 内,它将不起作用,您只会得到一个空图像。
Jaime Rodriguez 在他的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;
}
【讨论】:
这在您的代码隐藏中: (或通过窗口。)
不是我的,而是我的杂烩,并且在谷歌上搜索。适用于 .Net 5 和 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);
}
}
【讨论】: