Screen Capture


Introduction:

This function copies the entire screen into a .bmp file which is specified as parameter. Note that it only works properly in 24-bit (truecolor) mode, because it is assumed that every pixel uses three bytes.

Note that this function does not implement error handling for the sake of simplicity.

The Code:

void ScreenCapture(char* filename)
{
   // This function only works for 24-bit (truecolor) display mode

   // prepare DCs, bitmaps,..
   HDC hScreenDC = GetWindowDC(0);
   HDC hmemDC = CreateCompatibleDC(hScreenDC);   
   int ScreenWidth = GetDeviceCaps(hScreenDC, HORZRES);
   int ScreenHeight = GetDeviceCaps(hScreenDC, VERTRES);
   HBITMAP hmemBM = CreateCompatibleBitmap(hScreenDC, ScreenWidth, ScreenHeight);
   SelectObject(hmemDC, hmemBM);

   // copy screen to memory DC
   BitBlt(hmemDC, 0, 0, ScreenWidth, ScreenHeight, hScreenDC, 0, 0, SRCCOPY);

   // allocate and lock memory for the bitmap data
   HGLOBAL hpxldata = GlobalAlloc(GMEM_FIXED, ScreenWidth * ScreenHeight * 3);
   void FAR* lpvpxldata = GlobalLock(hpxldata);

   // fill .bmp - structures
   BITMAPINFO bmInfo;
   bmInfo.bmiHeader.biSize = 40;
   bmInfo.bmiHeader.biWidth = ScreenWidth;
   bmInfo.bmiHeader.biHeight = ScreenHeight;
   bmInfo.bmiHeader.biPlanes = 1;
   bmInfo.bmiHeader.biBitCount = 24;
   bmInfo.bmiHeader.biCompression = 0;
   bmInfo.bmiHeader.biSizeImage = 0;
   bmInfo.bmiHeader.biXPelsPerMeter = 0;
   bmInfo.bmiHeader.biYPelsPerMeter = 0;
   bmInfo.bmiHeader.biClrUsed = 0;
   bmInfo.bmiHeader.biClrImportant = 0;

   BITMAPFILEHEADER bmFileHeader;
   bmFileHeader.bfType = 19778;
   bmFileHeader.bfSize = (ScreenWidth * ScreenHeight * 3) + 40 + 14;
   bmFileHeader.bfReserved1 = 0;
   bmFileHeader.bfReserved2 = 0;
   bmFileHeader.bfOffBits = 54;

   // copy bitmap data into global memory
   GetDIBits(hmemDC, hmemBM, 0, ScreenHeight, lpvpxldata, &bmInfo, DIB_RGB_COLORS);

   // open file and write data
   int bmfile = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IWRITE);
   write(bmfile, &bmFileHeader, 14);
   write(bmfile, &bmInfo, 40);
   write(bmfile, lpvpxldata, ScreenWidth * ScreenHeight * 3);

   // clean up
   close(bmfile);
   GlobalUnlock(hpxldata);
   GlobalFree(hpxldata);
   DeleteObject(hmemBM);
   DeleteDC(hmemDC);
   ReleaseDC(0, hScreenDC);
}

Explanation:

The first thing the function does, is to prepare a memory device context and a memory bitmap, which has exactly the dimensions of the screen. The bitmap is necessary because GetDIBits uses a bitmap-handle as parameter. It is not possible to save the contents of the screen directly to a file, because GetDIBits requires a bitmap handle and, as far as I know, there is no such thing as a bitmap handle for the whole screen. . Then the whole screen is copied to the memory device context (using BitBlt). After that, global memory must be prepared to hold the pixel data of the memory bitmap before they can be saved to disk. The GlobalLock function is necessary because GetDIBits won't accept the handle of the memory object to write to (which you get with GlobalAlloc). Instead you have to specify the address (which you get using GlobalLock). After that, the structures for the .bmp-format are prepared. The calculation for the bfSize member of bmFileHeader is a little strange. The ScreenWidth multiplied with the ScreenHeight and 3 amount to the number of bytes used for the pixel data in a truecolor image, 40 is the size of bmInfo, 14 is the size of bmFileHeader. This results in the absolute size of the file in bytes. These structures become important later, when the file is saved. The next thing to do is to copy the pixel data from the memory bitmap, we created at the beginning, into the allocated memory. This is done using the function GetDIBits. The next part of the function uses the file I/O functions from the C++ header file io.h. If you want to use the ScreenCapture function in another programming language, you will have to use the I/O functions of your language or the API I/O functions. It should be clear, how the image data is saved (as a normal .bmp file). The last part of the function closes the file and deletes the used objects.

Back to the main page



Copyright 1998 Stefan Hetzl. If you have questions or comments or have discovered an error, send mail to [email protected]. You may forward this document or publish it on your webpage as long as you don't change it and leave this notice at the end.