Screen Capturing a Form in .NET - Using GDI and GDI+


Figure 1 - Form captured into a jpeg file

In most cases, GDI+ speeds up your programming of Graphics because (1) It is not a thin veneer over the Windows SDK (2) It makes sense.   However, whenever you lose granularity to create a simpler to use architecture, you tend to lose some functionality.  Form Capture is one of these cases. In the cases where you say to yourself: "Hey!  I could do that in GDI, why can't I do that in GDI+??".  The answer is you can.

C# has an attribute that allows you to bring in virtually any pre-millenium Windows SDK dll.  This, of course, includes the famed gdi.dll.  The way to do this is shown below using the DllImportAttribute:

[System.Runtime.InteropServices.DllImportAttribute("gdi32.dll")]

The way to do form capture in GDI is to get the device context to the screen and bit blast it to a Bitmap in memory.  The GDI external declaration for bit blasting is shown below (Note that this call has been converted to the equivalent call in C# so it can be used in our program):

private static extern bool BitBlt(
IntPtr hdcDest,
// handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
System.Int32 dwRop // raster operation code
); 

In order to use this GDI call in GDI+ you need to have hooks into the device contexts.  Luckily GDI+ provides a method of getting the GDI device context through the GDI+ graphics object:

IntPtr dc1 = aGraphicsObject.GetHdc();

Now we'll put the whole thing together in our Form.  Below is the series of calls needed to get the image from the form and stick it in a bitmap using the following steps:

  • Get a graphics object to the Form on the screen
  • Create an empty bitmap the size of the Form's Client Area
  • Get the Device Context for the Form
  • Get the Device Context for the Bitmap
  • Bit Blast the Form on the screen into the Bitmap
  • Release the Device Context for the Form
  • Release the Device Context for the Bitmap
  • Save the Image into a jpeg File

Remember, its important to release the GDI device context after your done using it to make the GDI call(s), otherwise GDI+ will have problems. Below is the full code for capturing the forms client area into a jpeg file:

private void Capture_Click(object sender, System.EventArgs e)
{
Graphics g1 =
this.CreateGraphics();
Image MyImage =
new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height, g1);
Graphics g2 = Graphics.FromImage(MyImage);
IntPtr dc1 = g1.GetHdc();
IntPtr dc2 = g2.GetHdc();
BitBlt(dc2, 0, 0,
this.ClientRectangle.Width, this.ClientRectangle.Height, dc1, 0, 0, 13369376);
g1.ReleaseHdc(dc1);
g2.ReleaseHdc(dc2);
MyImage.Save(@"c:\Captured.jpg", ImageFormat.Jpeg);
MessageBox.Show("Finished Saving Image");
}
 

Happy Bit Blasting!


Similar Articles