简体   繁体   English

WPF使用C#从UIElement截取JPG

[英]WPF Screenshot JPG from UIElement with C#

I'm trying to create a JPG from part of my WPF Applications. 我正在尝试从WPF应用程序的一部分创建JPG。 Like a screenshot, only of individual UIElement s. 就像截图一样,只有个别的UIElement I started here: http://www.grumpydev.com/2009/01/03/taking-wpf-screenshots/ 我从这里开始: http//www.grumpydev.com/2009/01/03/taking-wpf-screenshots/

I am using his extension method, which essential allows you to get a byte[] with UIElement.GetJpgImage() . 我正在使用他的扩展方法,该方法允许您使用UIElement.GetJpgImage()获取byte []。 This can then be written using a filestream to a JPG image. 然后可以使用文件流将其写入JPG图像。 If I make a JPG of the whole window, it looks just fine! 如果我制作整个窗口的JPG,它看起来很好! However, this is not ideal because it just captures what the user sees. 但是,这并不理想,因为它只捕获用户看到的内容。 Things that are not visible because of the scrollviewer or because their parent was animated to a small size won't show up. 因滚动查看器而无法显示的内容或因为其父级动画为小尺寸而无法显示的内容。

If I take a "screenshot" of, say, a grid that I use for layout: alt text http://img697.imageshack.us/img697/4233/fullscreenshot2.jpg 如果我拍摄一个“截图”,例如我用于布局的网格: alt text http://img697.imageshack.us/img697/4233/fullscreenshot2.jpg

I get this crap with a black background. 我得到了这个黑色背景的垃圾。 I don't want that. 我不希望这样。 Furthermore, if I've collapsed this grid's height using animation, I won't get anything at all. 此外,如果我使用动画折叠了这个网格的高度,我根本不会得到任何东西。 Those are actually templated checkboxes, they should have black text above them, and the background of the grid should be white. 这些实际上是模板化的复选框,它们上面应该有黑色文本,网格的背景应该是白色的。 Here's the code that someone else wrote to return the byte[] array that gets written to a filestream: 以下是其他人编写的代码,用于返回写入文件流的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;
}

Somewhere in there, we're getting a black background. 在那里的某个地方,我们得到了黑色背景。 Any insight? 任何见解?

EDIT: If I set the grid's background property to white, the screenshot comes out as expected. 编辑:如果我将网格的背景属性设置为白色,屏幕截图将按预期显示。 However, it's not feasible to set everything's background that I need to take a screenshot of. 但是,设置我需要截取屏幕截图的所有背景是不可行的。

Just a guess, I would think that a black background would represent portions of the byte array that are not set to anything in this process. 只是一个猜测,我认为黑色背景将代表字节数组中未在此过程中设置为任何内容的部分。 The initial zeros in the array would appear as black. 数组中的初始零将显示为黑色。

To avoid this, I suggest initializing the array with 0xFF (byte.MaxValue) values. 为避免这种情况,我建议使用0xFF(byte.MaxValue)值初始化数组。

UPDATED: 更新:

From looking at this closer, I think you should draw a white rectangle onto the image before you render the UI element. 从近距离观察,我认为你应该在渲染UI元素之前在图像上绘制一个白色矩形。 That ought to work anyway. 无论如何,那应该是有效的。

Just before this line of code 就在这行代码之前

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

put something like this 把这样的东西

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

Unfortunately the only thing that worked was just setting the element's background in the XAML. 不幸的是,唯一有效的方法就是在XAML中设置元素的背景。 I didn't want to do this, but I guess it is what I need to do in this case. 我不想这样做,但我想这是我在这种情况下需要做的事情。 Thanks anyway for the suggestion. 无论如何,谢谢你的建议。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM