Screen capture

Started by
6 comments, last by TheArtfulPianist 20 years, 10 months ago
Does anyone know how I can capture the whole screen within a program and save it to a bitmap or some other image format? Not just the rendering window, the whole screen, like printscreen button does. Thanks.
Advertisement
Can''t you do that using the Desktop window''s handle? -> MSDN

Crispy
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
push printscreen when you want the screen, open up the paint
program, choose the selection tool and do paste.
then save of course.
I''ll try the window handle thing...As for pushing printscreen I know that works, but I would like to be able to take full screenshots within a program and analyze them again within program.

You can capture the entire screen in the following way:

HDC hScreen, hMemDc;
HBITMAP hBitmap;
BITMAPINFO *bmiScreen;
BYTE *bmpBits, *tmpBits;
int nWidth, nHeight;

nWidth = GetSystemMetrics(SM_CXSCREEN);
nHeight = GetSystemMetrics(SM_CYSCREEN);

hScreen = GetDC(NULL);
hMemDc = CreateCompatibleDC(NULL);
hBitmap = CreateCompatibleBitmap(hScreen, nWidth, nHeight);

hBitmap = (HBITMAP)SelectObject(hMemDc, hBitmap);
BitBlt(hMemDc, 0, 0, nWidth, nHeight, hScreen, 0, 0, SRCCOPY);
ReleaseDC(NULL, hScreen);
hBitmap = (HBITMAP)SelectObject(hMemDc, hBitmap);

// hBitmap now contains the bits. You can convert them
// to 24bpp as follows

bmiScreen = (BITMAPINFO *)malloc(sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 256); // allow for 256 colors
memset(bmiScreen, 0, sizeof(BITMAPINFO)); // don''t really care about the color table right now

bmiScreen->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
GetDIBits(aMemDc, hBitmap, 0, nHeight, NULL, bmiScreen, DIB_RGB_COLORS);

// DWORD align the bitmap bits
int nRowSz, nPad;
nRowSz = nWidth * 3;
while (nRowSz & 3) nRowSz++;
nPad = nRowSz - nWidth * 3;

bmpBits = new BYTE[nRowSz * nHeight];
switch (bmiScreen->bmiHeader.biBitCount)
{
case 32:
case 24:
bmiScreen->bmiHeader.biBitCount = 24;
bmiScreen->bmiHeader.biCompression = BI_RGB;
bmiScreen->bmiHeader.biSizeImage = 0;
GetDIBits(aMemDc, hBitmap, 0, nHeight, (LPVOID)bmpBits, bmiScreen, DIB_RGB_COLORS);
break;

case 16:
{
int n16RowSz = width * 2;
while (width & 3) n16RowSz++; // DWORD align

tmpBits = new BYTE[n16RowSz * nHeight];
bmiScreen->bmiHeader.biSizeImage = 0;
bmiScreen->bmiHeader.biCompression = BI_RGB;
GetDIBits(aMemDc, hBitmap, 0, nHeight, (LPVOID)tmpBits, bmiScreen, DIB_RGB_COLORS);

int i, j;
BYTE *ptr = bmpBits;
for (i = 0; i < nHeight; i++)
{
for (j = 0; j < nWidth; j++)
{
WORD data = MAKEWORD(tmpBits[i*n16RowSz+j*2], tmpBits[i*n16RowSz+j*2+1]);
*ptr++ = (BYTE)((data & 0x1F) << 3);
*ptr++ = (BYTE)(((data >> 5) & 0x1F) << 3);
*ptr++ = (BYTE)(((data >> 10) & 0x1F) << 3);
}
for (j = nPad; j--; ) *ptr++ = 0;
}
delete tmpBits;
break;
}

case 8:
{
PALETTEENTRY palSys[256];
int n8RowSz;
GetSystemPaletteEntries(aMemDc, 0, 256, palSys);

n8RowSz = bmiScreen->bmiHeader.biWidth;
while (n8RowSz & 3) n8RowSz++;

bmiScreen->bmiHeader.biCompression = BI_RGB;
bmiScreen->bmiHeader.biClrUsed = bmiScreen->bmiHeader.biClrImportant = 256;

tmpBits = new BYTE[n8RowSz * nWidth];
GetDIBits(aMemDc, hBitmap, 0, nHeight, (LPVOID)tmpBits, bmiScreen, DIB_RGB_COLORS);

int i,j;
BYTE *ptr = bmpBits;
for (i = 0; i < nHeight; i++)
{
for (j = 0; j < nWidth; j++)
{
*ptr++ = palSys[tmpBits[i*n8RowSz+j]].peBlue;
*ptr++ = palSys[tmpBits[i*n8RowSz+j]].peGreen;
*ptr++ = palSys[tmpBits[i*n8RowSz+j]].peRed;
}
for (j = nPad; j--; ) *ptr++ = 0;
}
delete tmpBits;
break;
}

default:
break;
}

DeleteObject(hBitmap);
DeleteDC(hMemDc);

// update our bitmapinfoheader
bmiScreen->bmiHeader.biBitCount = 24;
bmiScreen->bmiHeader.biCompression = BI_RGB;
bmiScreen->bmiHeader.biSizeImage = 0;
bmiScreen->bmiHeader.biClrUsed = bmiScreen->bmiHeader.biClrImportant = 0;


// saving to a file as bitmap

BITMAPFILEHEADER bfhBmp;
memset(&bfhBmp, 0, sizeof(bfhBmp));
bfhBmp.bfType = MAKEWORD(''B'', ''M'');
bfhBmp.bfOffBits = sizeof(bfhBmp) + sizeof(BITMAPINFOHEADER);
bfhBmp.bfSize = bfhBmp.bfOffBits + nRowSz * nHeight;

FILE *fp = fopen("FILENAME", "w+b");
fwrite(&bfhBmp, sizeof(bfhBmp), 1, fp);
fwrite(bmiScreen, sizeof(BITMAPINFOHEADER), 1, fp);
fwrite(bmpBits, 1, nRowSz * nHeight, fp);
fclose(fp);

free(bmiScreen);
delete bmpBits;

/////////////////////////////////////////////////////////

Well then.. That''s a ton of code with no actual error checking Hopefully I didn''t mistype something.

Thanks, sedition, it worked like a charm!
How is possible to modify sedition code to bind the screen capture to a texture, instead of saving it to a bitmap file ?

I''ve a example for taking a screenshot on my website.

The program saves the screen to a TGA file.

========================
Leyder Dylan (dylan.leyder@slug-production.be.tf
http://www.slug-production.be.tf/
========================Leyder Dylan (dylan.leyder@slug-production.be.tf http://users.skynet.be/fa550206/Slug-Production/Index.htm/

This topic is closed to new replies.

Advertisement