(Print this page)

Taking a snapshot of a screen in WPF
Published date: Friday, October 30, 2015
On: Moer and Éric Moreau's web site

Lately, I had remote users testing one of my application. These users were not SnagIt users. They asked me to add a button to the application that will automatically create an email and attach the snapshot just taken.

So that was my inspiration for this month article.

Downloadable demo

This month downloadable solution has been created using Visual Studio 2015 but you can reuse the exact same code in older versions as well.

The solution contains both VB and C# code.

Creating a test UI

For the needs of the demo application, I have created a very sample form containing a grid showing dummy content coming from a previous article. The form also contains a button that when clicked will take a snapshot of the current form.

Figure 1: The demo application in action

Filling the datagrid is not the interesting part. So let’s jump right to the capture button!

Capturing the current UI Element

I have created an extension method that extends UIElement object type. This way, you could pass just a control instead of the whole form if you need a more specific capture.

This is the method that does the hard stuff:

<Runtime.CompilerServices.Extension>
Public Function CaptureUiElement(source As UIElement) As Byte()
    Dim height As Double = source.RenderSize.Height
    Dim width As Double = source.RenderSize.Width

    Dim dpi As Double = 96

    Dim renderTarget As New RenderTargetBitmap(CInt(width), CInt(height), 
                                               dpi, dpi, PixelFormats.Pbgra32)

    Dim drawingVisual As New DrawingVisual()
    Dim drawingContext As DrawingContext = drawingVisual.RenderOpen()

    Using drawingContext
        drawingContext.DrawRectangle(New VisualBrush(source), 
                                     Nothing, 
                                     New Rect(New Point(0, 0), New Point(width, height)))
    End Using
    renderTarget.Render(drawingVisual)

    Dim jpgEncoder As New JpegBitmapEncoder()
    jpgEncoder.QualityLevel = 90
    jpgEncoder.Frames.Add(BitmapFrame.Create(renderTarget))

    Dim imageArray As Byte()
    Using outputStream As New MemoryStream()
        jpgEncoder.Save(outputStream)
        imageArray = outputStream.ToArray()
    End Using

    Return imageArray
End Function

This method extends a UIElement (available in the source parameter). Using the size of this element, a jpeg (using the JpegBitmapEncoder from the System.Windows.Media.Imaging library) is created in a byte array and returned to the caller.

Using that method

Now that we have this method in place, it is quite easy to use.

The first thing you need to do is to call the CaptureUiElement method. As shown in the following code snippet, it is currently called on Me (for VB or this for C#) meaning that we want the whole form.

Once you have the byte array, you can for example save it using a BinaryWriter.

The complete code to capture the screen and save the file reads like this:

Private Sub ButtonCapture_Click(sender As Object, e As RoutedEventArgs)
    'get a byte array containing the screen shot
    Dim screenshot As Byte() = Me.CaptureUiElement()

    'save the byte array in a file in the current folder
    Using fileStream As New FileStream(String.Format("Screenshot_{0}.jpg", DateTime.Now.ToString("yyyyMMdd_HHmmss")), 
                                       FileMode.Create, FileAccess.ReadWrite)
        Using binaryWriter As New BinaryWriter(fileStream)
            binaryWriter.Write(screenshot)
            binaryWriter.Close()
        End Using
    End Using
End Sub

As explained earlier, I could have use “GridData.CaptureUiElement()” as well to only get the image of the grid.

Emailing the image

I haven’t included the code here to attach the image to an email. I will refer you to a previous article from “Sending e-mails with attachments (a different method)”.

Conclusion

This feature is not very complex and can be very helpful for many users not using tools like SnagIt and don’t want to learn to use the free snipping tool.


(Print this page)