WPF使用C#从UIElement截取JPG

时间:2010-06-04 20:02:09

标签: c# wpf wpf-controls screenshot uielement

我正在尝试从部分WPF应用程序创建JPG。就像截图一样,只有个人UIElement。我从这里开始:http://www.grumpydev.com/2009/01/03/taking-wpf-screenshots/

我正在使用他的扩展方法,该方法允许您使用UIElement.GetJpgImage()获取byte []。然后可以使用文件流将其写入JPG图像。如果我制作整个窗口的JPG,它看起来很好!但是,这并不理想,因为它只捕获用户看到的内容。因滚动查看器而无法显示的内容或因为其父级动画为小尺寸的内容将无法显示。

如果我拍摄一个“截图”,例如我用于布局的网格: alt text http://img697.imageshack.us/img697/4233/fullscreenshot2.jpg

我得到了这个黑色背景的废话。我不希望这样。此外,如果我使用动画折叠了这个网格的高度,我根本不会得到任何东西。这些实际上是模板化的复选框,它们上面应该有黑色文本,网格的背景应该是白色的。这是其他人编写的代码,用于返回写入文件流的byte []数组:

public static byte[] GetJpgImage(this UIElement source, double scale, int quality)
{
    double actualHeight = source.RenderSize.Height;
    double actualWidth = source.RenderSize.Width;

    double renderHeight = actualHeight * scale;
    double renderWidth = actualWidth * scale;

    RenderTargetBitmap renderTarget = new RenderTargetBitmap((int) renderWidth, (int) renderHeight, 96, 96, PixelFormats.Pbgra32);
    VisualBrush sourceBrush = new VisualBrush(source);

    DrawingVisual drawingVisual = new DrawingVisual();
    DrawingContext drawingContext = drawingVisual.RenderOpen();

    using (drawingContext)
    {
        drawingContext.PushTransform(new ScaleTransform(scale, scale));
        drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight)));
    }
    renderTarget.Render(drawingVisual);

    JpegBitmapEncoder jpgEncoder = new JpegBitmapEncoder();
    jpgEncoder.QualityLevel = quality;
    jpgEncoder.Frames.Add(BitmapFrame.Create(renderTarget));

    Byte[] _imageArray;

    using (MemoryStream outputStream = new MemoryStream())
    {
        jpgEncoder.Save(outputStream);
        _imageArray = outputStream.ToArray();
    }

    return _imageArray;
}

在那里的某个地方,我们正在获得黑色背景。有什么见解吗?

编辑:如果我将网格的背景属性设置为白色,屏幕截图会按预期显示。但是,设置我需要截取屏幕截图的所有背景是不可行的。

2 个答案:

答案 0 :(得分:6)

只是一个猜测,我认为黑色背景将代表字节数组中未在此过程中设置为任何内容的部分。数组中的初始零将显示为黑色。

为避免这种情况,我建议用0xFF(byte.MaxValue)值初始化数组。

更新:

从近距离观察,我认为你应该在渲染UI元素之前在图像上绘制一个白色矩形。无论如何,这应该有用。

就在这行代码之前

drawingContext.DrawRectangle(sourceBrush, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight))); 

这样的东西

drawingContext.DrawRectangle(Brushes.White, null, new Rect(new Point(0, 0), new Point(actualWidth, actualHeight))); 

答案 1 :(得分:0)

不幸的是,唯一有效的方法就是在XAML中设置元素的背景。我不想这样做,但我想这是我在这种情况下需要做的事情。无论如何,谢谢你的建议。