[英]WPF Screenshot JPG from UIElement with C#

I'm trying to create a JPG from part of my WPF Applications. Like a screenshot, only of individual UIElements. I started here: 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(). This can then be written using a filestream to a JPG image. If I make a JPG of the whole window, it looks just fine! 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.

我正在使用他的擴展方法,該方法允許您使用UIElement.GetJpgImage()獲取byte []。然后可以使用文件流將其寫入JPG圖像。如果我制作整個窗口的JPG,它看起來很好!但是,這並不理想,因為它只捕獲用戶看到的內容。由於滾動查看器而無法顯示的內容或因為其父級動畫為小尺寸而無法顯示的內容。

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)));

    JpegBitmapEncoder jpgEncoder = new JpegBitmapEncoder();
    jpgEncoder.QualityLevel = quality;

    Byte[] _imageArray;

    using (MemoryStream outputStream = new MemoryStream())
        _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.


2 个解决方案



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.



From looking at this closer, I think you should draw a white rectangle onto the image before you render the UI element. 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. 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.




  © 2014-2022 ITdaan.com 联系我们: