Demo for Screen Capture in C#


This link can be used to download a demo project that shows how to do screen captures in C#.



Below, I show the step-by-step process of coding a simple Winforms application in C# to capture the screen in a screenshot.

It was not possible to capture the contents of the desktop using the early versions of the .NET framework without resorting to Windows API calls. The .NET framework 2.0 introduced several new and modified classes within the System.Drawing and System.Drawing.Imaging namespaces that make the job much simpler. Instead of using API calls, the Graphics Device Interface 'plus' (GDI+) system that was introduced in Windows XP, and is provided in later operating systems, is utilised. To demonstrate, we will create a simple Windows Forms program that copies the contents of the screen onto the background of its main form on loading. The image will be the same as that copied to the clipboard when the Print Screen key is pressed. To begin, create a new Windows Forms application. The entire code for this sample will be held in the form's Load event so add this event using the development environment of your choice. In the example we are using the PrimaryScreen property to examine the contents of the main display. If multiple monitors are in use, the AllScreens array can be used to capture the other displays.

Note: All of the following comments and code can be copy-pasted into the Form1_Load() method of a C# Winforms project, but you'll learn more if you read the explanation, and add each line of code as you understand what has been explained:


		
			/* The bitmap image will be created with a fixed size. This size must match the screen resolution 
			exactly or the image will be cropped or contain blank areas that are simply wasting resources. 
			To determine the screen resolution, add the following code to the Load event: */

            Rectangle bounds = Screen.PrimaryScreen.Bounds;
            
            /* The colour depth for the screen is measured in bits per pixel. Usual values for number 
            of bits used per pixel are 8, 16, 24 and 32. The higher the number of bits, the more 
            colours can be represented in each screen pixel giving improvements in graphical quality 
            at the cost of memory usage. We will identify the colour depth and use a similar value for 
            the bitmap so that memory usage is minimised.

            To determine the colour depth, add the following code: */
            
            int colourDepth = Screen.PrimaryScreen.BitsPerPixel;

            /* 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 palette-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;

                default:
                    format = PixelFormat.Format32bppArgb;
                    break;
            }

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

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

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

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

            /* 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;

            //let's save the image in PNG format, in the application's directory:
            captured.Save("saved.png", ImageFormat.Png);