How to create a screenshot from code

A co-worker came up with some code for this. I changed it up just a tad and wanted to save it. This allows you to easily take a screenshot of an application, from inside the application. This can be useful for capturing errors that the user sees for example. Here’s how you would do it. I made one sealed class with one method to call. This class has no exception handling (for clarity’s sake) – but you should definitely add some:
 

using System;

using System.Drawing;

using System.Drawing.Imaging;

using System.Runtime.InteropServices;

 

/// <summary>

/// Utility class to create a screenshot of a window.

/// </summary>

internal sealed class ScreenCapture

{

    #region Native Methods

    [DllImport("GDI32.dll")]

    private static extern bool BitBlt(int hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, int hdcSrc, int nXSrc, int nYSrc, int dwRop);

    [DllImport("GDI32.dll")]

    private static extern int CreateCompatibleBitmap(int hdc, int nWidth, int nHeight);

    [DllImport("GDI32.dll")]

    private static extern int CreateCompatibleDC(int hdc);

    [DllImport("GDI32.dll")]

    private static extern bool DeleteDC(int hdc);

    [DllImport("GDI32.dll")]

    private static extern bool DeleteObject(int hObject);

    [DllImport("GDI32.dll")]

    private static extern int GetDeviceCaps(int hdc, int nIndex);

    [DllImport("GDI32.dll")]

    private static extern int SelectObject(int hdc, int hgdiobj);

    [DllImport("User32.dll")]

    private static extern int GetDesktopWindow();

    [DllImport("User32.dll")]

    private static extern int GetWindowDC(int hWnd);

    [DllImport("User32.dll")]

    private static extern int ReleaseDC(int hWnd, int hDC);

    #endregion

 

    /// <summary>

    /// Data structure to hold window dimension information.

    /// </summary>

    public struct WindowDimensions

    {

        public WindowDimensions(int height, int width)

        {

            this.windowHeight = height;

            this.windowWidth = width;

        }

 

        public int WindowWidth

        {

            get { return windowWidth; }

            set { windowWidth = value; }

        } int windowWidth;

        public int WindowHeight

        {

            get { return windowHeight; }

            set { windowHeight = value; }

        } int windowHeight;

    }

 

    /// <summary>

    /// Takes a screen shot of a window.

    /// </summary>

    public static void CaptureScreen(string fileName, ImageFormat imageFormat, int windowHandle, WindowDimensions windowSize, bool negativeColors)

    {

        int deviceContext = GetWindowDC(windowHandle),

            destinationDeviceContext = CreateCompatibleDC(deviceContext),

            bitmap = CreateCompatibleBitmap(deviceContext, windowSize.WindowWidth, windowSize.WindowHeight);

        SelectObject(destinationDeviceContext, bitmap);

 

        if (negativeColors)

        {

            BitBlt(destinationDeviceContext, 0, 0, windowSize.WindowWidth, windowSize.WindowHeight, deviceContext, 0, 0, 0x00330008);

        }

        else

        {

            BitBlt(destinationDeviceContext, 0, 0, windowSize.WindowWidth, windowSize.WindowHeight, deviceContext, 0, 0, 0x00CC0020);

        }

 

 

        SaveImage(bitmap, fileName, imageFormat);

        Cleanup(bitmap, deviceContext, destinationDeviceContext);

    }

 

 

    /// <summary>

    /// Release screen capture resources

    /// </summary>

    private static void Cleanup(int bitmap, int deviceContext, int destinationDeviceContext)

    {

        ReleaseDC(GetDesktopWindow(), deviceContext);

        DeleteDC(destinationDeviceContext);

        DeleteObject(bitmap);

    }

 

 

    /// <summary>

    /// Writes the captured image to a file in the specified format

    /// </summary>

    private static void SaveImage(int bitmap, string fileName, ImageFormat imageFormat)

    {

        Bitmap image = new Bitmap(Image.FromHbitmap(new IntPtr(bitmap)),

        Image.FromHbitmap(new IntPtr(bitmap)).Width,

        Image.FromHbitmap(new IntPtr(bitmap)).Height);

        image.Save(fileName, imageFormat);

    }

}

And then to consume this (take a screen show of the current Windows form), you would do something like this:

    // You need to call this, because otherwise the window manager

    // won’t update, if the window was resized for example (generates an invalid picture)

    this.RecreateHandle();

 

    // Then give the UI a second to finish that

    Application.DoEvents();

 

    // Now capture the screen

    ScreenCapture.CaptureScreen(@"C:Screenshot.jpg",

        ImageFormat.Jpeg, this.Handle.ToInt32(),

        new ScreenCapture.WindowDimensions(this.Height, this.Width), false);

 

Posted in Uncategorized, WinForms

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archives
Categories

Enter your email address to follow this blog and receive notifications of new posts by email.

Join 4 other followers

%d bloggers like this: