BlackWaspTM
Graphics
.NET 2.0+

Capturing the Screen Contents in .NET 2.0 (2)

When supporting installed software, descriptions of problems can be enhanced greatly by viewing the contents of the user's screen. In this article we will explore how to perform a screen grab and display the captured image in a Windows Forms application.

Selecting the Pixel Format

To create a bitmap object with a specific number of bits per pixel, a PixelFormat structure must be created. This data type specifies information relating to pixel formats that may be used by GDI+ when working with images. The structure contains some pre-defined constants that can be used to specify the various bit-depths required.

One limitation of the screen capturing method is the inability to capture a bitmap with eight bits per pixel. This is due to the image being pallet-based rather than defined as an RGB value. To avoid this problem, if the screen is set to use 256 colours (8-bit), the captured image will use a sixteen-bit colour depth.

The following code creates a new PixelFormat structure and assigns its value according to the colour depth identified earlier. The switch statement includes a default option that uses thirty-two bits per pixel. This is used if the colour depth is not one of the expected values.

PixelFormat format;
switch (colourDepth)
{
    case 8:
    case 16:
        format = PixelFormat.Format16bppRgb565;
        break;

    case 24:
        format = PixelFormat.Format24bppRgb;
        break;

    case 32:
        format = PixelFormat.Format32bppArgb;
        break;

    default:
        format = PixelFormat.Format32bppArgb;
        break;
}

Initialising the Bitmap

Now that the size and number of colours for the final image is known, a Bitmap object can be initialised. Add the following to create the image, which will be named 'captured'.

Bitmap captured = new Bitmap(bounds.Width, bounds.Height, format);

Creating a GDI+ Drawing Surface

To use the GDI+ functions, a drawing surface must be created. The drawing surface is linked to the bitmap so that all activities performed affect the bitmap's contents. The Graphics class' FromImage method returns a correctly linked drawing surface.

Add the following line to create the drawing surface:

Graphics gdi = Graphics.FromImage(captured);

Copying the Screen Contents

With the GDI+ drawing surface prepared, the screen contents can now be captured. The Graphics class defines a method named CopyFromScreen for this purpose. The variant that we will use requires five parameters.

The first two parameters contain the co-ordinates of the top-left pixel to be captured. This can be found in the 'bounds' variable initialised earlier. The third and fourth parameters hold the co-ordinates in the drawing surface where we wish the copied image to be positioned. As we wish to copy to the top-left of the image, these are both set to zero. Setting a different pair of values allows the copying to be repositioned, cropping edges and creating margins. Finally, the size of the area to be copied is required. This again comes from the 'bounds' variable.

Add the following code to capture the screen and copy it into the Bitmap object.

gdi.CopyFromScreen(bounds.Left, bounds.Top, 0, 0, bounds.Size);

Displaying the Screen Grab

The process is now complete and the screenshot exists within the Bitmap object. All that remains is to display the image in the background of the form. To ensure that the width:height ratio of the image is preserved, the background will be set to 'zoom mode' before assigning the image.

To complete the program, add the following code. Then execute the application to see the results.

this.BackgroundImageLayout = ImageLayout.Zoom;
this.BackgroundImage = captured;
10 February 2008