【问题标题】:Get a bitmap image from a Control view从控制视图中获取位图图像
【发布时间】:2010-03-26 10:11:13
【问题描述】:

我想将Control 的WPF 应用程序在屏幕上绘制的内容“复制到剪贴板”。 因此,我需要从我的 Control 当前显示中构建一个位图图像。

有没有简单的方法可以做到这一点?

提前致谢。

【问题讨论】:

标签: wpf


【解决方案1】:

我认为这并不容易......但关键组件是 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 对其进行转换。

【讨论】:

  • 谢谢,这是我的回答。好在 Clipboard.SetImage() 需要一个 BitmapSource,所以我可以直接给它 RenderTargetBitmap。奇迹般有效。你可以说它很容易。再次感谢 !现在我需要弄清楚如何允许用户在将其导出到固定分辨率位图之前操纵控件视觉(本质上是缩放它)。我想我会将当前显示复制为 Viewbox 中的 VisualBrush,并让用户在导出之前使用它。
  • 值得注意的是,虽然这适用于普通 WPF 组件,但任何仅包装来自不同空域的组件的特殊控件(如 Webbrowser 控件)都与 RenderTargetBitmap 不兼容。
  • 感谢过去的自己! 8 年后,我又一次想将 WPF 控件保存到流中。但我只是不记得它是如何工作的。所以我用谷歌搜索它,令我惊讶的是,我最终阅读了我自己的答案。 :D
  • 如何捕捉同样不在屏幕上的整个控件?
【解决方案2】:

如果您尝试从中创建位图的控件位于 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;
}

【讨论】:

    【解决方案3】:

    这在您的代码隐藏中: (或通过窗口。)

    不是我的,而是我的杂烩,并且在谷歌上搜索。适用于 .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);
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-07-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多