WPF使用C#從UIElement截取JPG

[英]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/

我正在嘗試從我的部分WPF應用程序創建JPG。就像截圖一樣,只有個別的UIElements。我從這里開始: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)));
    }
    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.

編輯:如果我將網格的背景屬性設置為白色,屏幕截圖將按預期顯示。但是,設置我需要截取屏幕截圖的所有背景是不可行的。

2 个解决方案

#1


5  

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. That ought to work anyway.

從近距離觀察,我認為你應該在渲染UI元素之前在圖像上繪制一個白色矩形。無論如何,這應該是有效的。

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

#2


0  

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.

不幸的是,唯一有效的方法就是在XAML中設置元素的背景。我不想這樣做,但我想這是我在這種情況下需要做的事情。無論如何,謝謝你的建議。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2010/06/04/fb59bce41c70157d1b9a5e5b8fa9846e.html



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