Taking a screen shot

by Kent Reisdorph

Last month in the article, “Simulating keystrokes”, I explained how to take a screen shot using the keybd_event() function. That method, however, places the bitmap image in the clipboard. You may prefer to take a screen shot and save that screen shot to a file on disk. This is accomplished fairly easily using a TCanvas and a TBitmap.

When it comes down to it, the Windows desktop is nothing more than one big bitmap. It may appear that you have several different Windows layered upon one another, but that is purely perception. The basic concept behind taking a screen shot, then, is to copy a portion of the desktop to a TBitmap and then save it using the SaveToFile() method.

The first step is to create an instance of TCanvas that represents the desktop’s device context (DC). The Windows API function GetDC() will return a device context handle for any window. Normally you pass the window handle of the window for which you want a device context to GetDC(). To get a handle to the desktop DC, though, you simply pass 0 to GetDC() as shown here:

TCanvas* dtCanvas = new TCanvas;
dtCanvas->Handle = GetDC(0);

The next step is to create a TBitmap instance and set its width and height as needed. If you are capturing your application’s main form you can use code like this:

Graphics::TBitmap* 
  bitmap = new Graphics::TBitmap;
bitmap->Width = Width;
bitmap->Height = Height;

Once you have a TCanvas for the desktop DC and the TBitmap, you need to copy the exact portion of the desktop that your application occupies to the TBitmap. To begin with you determine the position and size of your application’s window. The VCL makes this easy by providing the BoundsRect() method of TForm. Next you create a second TRect instance representing the location within the TBitmap where the screen bits will be copied. The code for these two steps looks like this:

TRect src = BoundsRect;
TRect dest = Rect(0, 0, Width, Height);

The final step is to copy the pixels contained in the source rectangle from the TCanvas to the TBitmap and save the bitmap to disk:

bitmap->Canvas->CopyRect(
  dest, dtCanvas, src);
bitmap->SaveToFile("form.bmp");

Naturally you need to free the memory allocated for these objects before you are done:

delete bitmap;
delete dtCanvas;

The resulting BMP file’s color depth will be determined by the system’s current settings (256 color, 16-bit color, 32-bit color, and so on). If you want to change the color depth of the BMP file then you will need to do a bit more work, but TBitmap has the functionality you need.

I should add that this code simply copies a portion of the screen to the TBitmap. If part of your application is obscured by another window, then that window will also show in the final BMP image. Also, be aware that there is no way to copy any part of a window that is off the screen or otherwise hidden. Still, this technique is easy to implement and is something you may find useful.