Skip navigation links
Home
Document Center
Blog
Videos
Forum
PhillyXAML.org > Blog > Posts > How can I save a WPF Application screen or control as an image?
How can I save a WPF Application screen or control as an image?
Wouldn't it be nice if you could easily save a WPF Application screen? Sure, we could always use an Alt-PrtScr to do a screengrab of the window, but wouldnt it be nice if we could click a button and be prompted for a save path to actually save the image, instead of having to open some other program, like Expression Design or Photoshop or Gimp and paste the clipboard into a new document, then save it? Wouldnt it be even nicer to be able to export just a portion of the screen like a grid or a Panel of some kind?
 
Using a RenderTargetBitmap object, we can render a System.Windows.Media.Visual to a virtual bitmap image that we can consume in other ways. In this example, we will use the RenderTargetBitmap to render out our control, and return a System.Drawing.Image object based on that bitmap.
 
The method takes a FrameworkElement object as an argument, which derives from Visual, through UIElement. The only reason I chose this for this example is because FrameworkElement has ActualWidth and ActualHeight properties available I can use to generate the image the correct size. Additionally, the UIElement and Visual classes are conceptually abstract meaning the objects you would pass to this method, are likely derived from these two classes, as opposed to being these types specifically. Since Control derives from FrameworkElement, as do most of the layout containers, like DockPanel, Grid, etc. we can easily pass any part of the UI to the method and get an Image back.
 
In order for this code to work, you will need to add using statements for System.Windows.Media, System.Windows.Media.Imaging, System.IO, and System.Drawing.

public static Image GetImage(FrameworkElement controlToRender, double resolution)
{
    RenderTargetBitmap rtb = new RenderTargetBitmap(
      (int)controlToRender.ActualWidth,
      (int)controlToRender.ActualHeight,
      resolution,
      resolution,
      PixelFormats.Pbgra32);

    rtb.Render(controlToRender);

    JpegBitmapEncoder jbe = new JpegBitmapEncoder();
    jbe.Frames.Add(BitmapFrame.Create(rtb));
    MemoryStream ms = new MemoryStream();
    jbe.Save(ms);
    Image retImg = Image.FromStream(ms);
    return retImg;
}
 
Once we have the Image object, we can easily assign it to a valid property, or we can save it using the Image.Save() method. You will need to add a reference to System.Windows.Forms to use the SaveFileDialog for this example. In the example below rDisplay is any object that could exist in our UI, that we are passing to the method.
 
SaveFileDialog dlg = new SaveFileDialog();
dlg.DefaultExt = ".jpg";
dlg.Filter = "JPEG Image (*.jpg)|*.jpg";
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
    System.Drawing.Image img = GetImage(rDisplay, 96);
    img.Save(dlg.FileName);
    MessageBox.Show("Image Saved");
}

Comments

There are no comments yet for this post.