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.