Screen Capture Utility in C# and .NET

Submitted ByUser LevelDate of Submission
Michael GoldIntermediate4/15/2002

Figure 1 - Screen Capturing the .NET environment

Source Code: ScreenCaptureDotNet.zip

After I created my article on Form Capture, I seemed to get quite a few inquiries on how to do a more useful function using .NET: Screen Capture. It turns out that screen capture is done in a much similar fashion. You still bring in the GDI API, but you also need to bring in the CreateDC API call. Below is the code for screen capture:

private void PerformCapture()
{
// turn the form invisible so you don't show it during capture
this.Visible = false;

//use the GDI call and create a DC to the whole display
IntPtr dc1 = CreateDC("DISPLAY", null, null, (IntPtr)null);

//create a Graphics object for the screen dc
Graphics g1 = Graphics.FromHdc(dc1);

// create a compatible bitmap the size of the entire screen
MyImage = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, g1);

// use the bitmap to create another Graphics surface  so we can  BitBlast into the bitmap
Graphics g2 = Graphics.FromImage(MyImage);

//  Now go retrace our steps and get the device contexts for both the bitmap and the screen
// Note:  Apparently you have to do this, and can't go directly from the aquired dc or exceptions are thrown
//            When you try to release the dcs
dc1 = g1.GetHdc();
IntPtr dc2 = g2.GetHdc();

//  Bit Blast  the screen into the Bitmap
BitBlt(dc2, 0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height, dc1, 0, 0, 13369376);

//   Remember to release the dc's, otherwise problems down the road
g1.ReleaseHdc(dc1);
g2.ReleaseHdc(dc2);

// Save the image to JPEG file
MyImage.Save(@"c:\Captured.jpg", ImageFormat.Jpeg);

//  Now we can view our form again, so make it visible
Visible = true;
MessageBox.Show("Finished Saving Image");

// Set the Bounds of the form so that it fills the entire screen
// Because in our Paint event handler we are going to draw the bitmap to the form
this.SetBounds(0, 0, Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);

//  ************** Set up functions for doing additional bitmap manipulation such as cropping a portion of 
//  ************* the image ****************(Not required for screen capture)

SetupCropping();
firstCrop = true;
}

This application has a few additional functions. One is that you can crop a piece of the image in your screen capture as shown in figure 2:

Figure 2 - Cropping a Piece of the image

This is useful for pulling things out of the screen capture that you find necessary in your final image. Outlining the cropping region is performed using the MouseDown, MouseUp, and MouseMove event handlers. You need to maintain the state in which the cropping is in in order to successfully draw the cropping region. Below is the state diagram for tracking the drawing of the crop rectangle.

Figure 3 - UML State Chart of Cropping Drawn with WithClass 2000

Below is the code for the MouseMove event handler. As shown in the state diagram, it checks the state and condition to see if we should be doing the calculation on the cropping rectangle and if we should invalidate the rectangle.

private void Form1_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
    // Check the state and condition to makes sure we can draw the cropping rectangle
    if ((CroppingPaint && CropOn) && StartedCrop)
    {
        // calculate width of cropping rectangle
        DeltaX = e.X - StartPoint.X;
        if (DeltaX < 0)
            DeltaX = 0;
        DeltaY = e.Y - StartPoint.Y;
        if (DeltaY < 0)
            DeltaY = 0;

        // force the cropping rectangle to redraw
        Invalidate(new Rectangle(StartPoint.X, StartPoint.Y, DeltaX + 20, DeltaY + 20));
    }
}

Improvements

The cropping invalidation is a little messy, it needs to add rubber-banding functionality to the line drawing of the rectangle. Also I had to offset the image to get the cropping to work out the first time through the capture. Not sure if its something I'm missing or a problem, but its in there like a band-aid. <g> Some nice improvements might include an undo, to undo cropping, the ability to put the image into a specified file rather than in c:\\capture.jpg. (Currently this is where the image is placed when its captured or saved). Additional features would be to save the image in different image formats, include a preference dialog for suffixes and prefixes to the captured image name, add a feature to enter text into the captured image. As with other projects in .NET the sky is the limit, but its a snap to add many of these additional functions using this environment. Stay tuned to C# Corner for the next version.


About the Author: Mike Gold is President of Microgold Software Inc. and Creator of WithClass 2000 a UML Design Tool for C#. In the last few years Mike has consulted for companies such as Merrill Lynch and Chase Manhattan Bank in New York. He is been active in developing Visual C++ Applications for 10 years and looks forward to the possibilities in C#. You can reach him at techsupport@microgold.com.


Contributors: FHL