SIGN UP MEMBER LOGIN:    
ARTICLE

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

Posted by Mike Gold Articles | GDI+ & Graphics September 15, 2001
This article shows 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.
Reader Level:
Download Files:
 

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!

Login to add your contents and source code to this article
share this article :
post comment
 

Hello Mike,

I have a big C# project that contains up to 600 forms.  My task is to collect all those static forms and save them as pictures (i.e. bmp, jpg).  Viewing the forms could easily be done manually but going to the IDE and View Designer for all those *.Designer.cs files.  However, I would like to automate this.  Do you have an idea?  I'd greatly appreciate it.

My email is htvnsp@yahoo.com.

Thank you very much for your help!
Peter

Posted by p nguyen Jun 01, 2010

I have used this code successfully to capture the Active Window; although I had to increase the height setting to get more of the message, buttons, etc. However, I am Not able to get the TITLEBAR of the active window, which is useful if you are trying to capture an applications error, which is displayed in the active window. Does anyone know how to modify the code to also acquire the titlebar of the active window?

Posted by RICHARD ARNOLD May 17, 2007

What is the proper way to handle BitBlt errors.With the above program (+ error handling) I'm getting "Invalid Handle" after locking my Desktop (running with XP).

Posted by Arko kundu Feb 28, 2007

I can't believe how easy its to create an image of my control. I've been struggling for months trying to figure a way to capture and save. I copied the Capture_Click method as my btn handler and added: using System.Drawing.Imaging; to my form. VIOLA. it WORK!! Create example. Now i'm trying to figure a way for the user to edit the image with comments, cropping, and simple lines... Any hints there :) Thanks for the code and post.

Posted by stockboy3000 Feb 11, 2007

I have developed a toolbar which is supposed to run in everybody's computer at the top of their screen but when another application is maximized it is covering the toolbar. is there a way to change the screen working area properties so that my form is not covered by anyother application maximized? basicaly it will be like the windows statusbar. thanks for any help. Naveed

Posted by ahmad naveed sorush Feb 06, 2007
Become a Sponsor
PREMIUM SPONSORS
  • The leading .NET charting control now features PDF, Flash and Silverlight export, visualization of large datasets and more. Deliver true charting functionality to your BI, Scorecard, Presentation or Scientific apps. Download evaluation now.
    Get 2 Months Free of ASP.NET Hosting for Only $4.95/month! Receive FREE MS SQL and MySQL Databases Including ASP.NET 4/3.5, MVC 3.0, Silverlight 4, Windows 2008/IIS 7.0 Plus FREE IIS 7 Modules. Host UNLIMITED ASP.NET Web Sites - Click Here!
Nevron Gauge for SharePoint
Become a Sponsor