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!