Capturing Desktop Screenshot to File in C


Here’s a simple function that helps you dump screenshots into files. By calling CaptureDesktopScreenshotToFile you can simply get the screenshot without dealing with any GDI yourself.

#include <windows.h>

int main()
{
CaptureDesktopScreenshotToFile("screenshot.bmp");

return 0;
}

And here’s the code for you.

#include <windows.h>

PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp);
int CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC);
int CaptureDesktopScreenshotToFile(char *FILENAME)
{
HDC hdcScreen,hdcCompatible;
HBITMAP hbmScreen;
hdcScreen = CreateDC("DISPLAY", NULL, NULL, NULL); 
hdcCompatible = CreateCompatibleDC(hdcScreen);

// Create a compatible bitmap for hdcScreen. 
int ScreenWidth = GetDeviceCaps(hdcScreen, HORZRES);
int ScreenHeight = GetDeviceCaps(hdcScreen, VERTRES);
hbmScreen = ::CreateCompatibleBitmap(hdcScreen,ScreenWidth,ScreenHeight);

if(hbmScreen == 0)
return 0;

// Select the bitmaps into the compatible DC
if(!::SelectObject(hdcCompatible, hbmScreen)) 
return 0;

if(!::BitBlt(hdcCompatible,0,0,ScreenWidth,ScreenHeight,hdcScreen,0,0,SRCCOPY)) 
return 0;

// Clean Tmp
DeleteFile(FILENAME);

// Take shot
if(CreateBMPFile(FILENAME,CreateBitmapInfoStruct(hbmScreen),hbmScreen,hdcScreen)​​ == 0)
return 0;

// Compression
//bmp2jpeg(DIRECTORY_TMP, DIRECTORY_TMP);

return 1;
}

int CreateBMPFile(LPTSTR pszFile, PBITMAPINFO pbi, HBITMAP hBMP, HDC hDC) 
{ 
HANDLE hf; // file handle 
BITMAPFILEHEADER hdr; // bitmap file-header 
PBITMAPINFOHEADER pbih; // bitmap info-header 
LPBYTE lpBits; // memory pointer 
DWORD dwTotal; // total count of bytes 
DWORD cb; // incremental count of bytes 
BYTE *hp; // byte pointer 
DWORD dwTmp; 

pbih = (PBITMAPINFOHEADER) pbi; 
lpBits = (LPBYTE) GlobalAlloc(GMEM_FIXED, pbih->biSizeImage);

if(!lpBits) 
return 0; 

// Retrieve the color table (RGBQUAD array) and the bits 
// (array of palette indices) from the DIB. 
if(!GetDIBits(hDC, hBMP, 0, (WORD) pbih->biHeight, lpBits, pbi, DIB_RGB_COLORS)) 
return 0;

// Create the .BMP file. 
hf = CreateFile(pszFile, GENERIC_READ | GENERIC_WRITE, (DWORD) 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, (HANDLE) NULL); 
if(hf == INVALID_HANDLE_VALUE) 
return 0;

hdr.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"
// Compute the size of the entire file. 
hdr.bfSize = (DWORD) (sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof(RGBQUAD) + pbih->biSizeImage); 
hdr.bfReserved1 = 0;
hdr.bfReserved2 = 0;

// Compute the offset to the array of color indices. 
hdr.bfOffBits = (DWORD) sizeof(BITMAPFILEHEADER) + pbih->biSize + pbih->biClrUsed * sizeof (RGBQUAD); 

// Copy the BITMAPFILEHEADER into the .BMP file.
if(!WriteFile(hf, (LPVOID) &hdr, sizeof(BITMAPFILEHEADER),(LPDWORD) &dwTmp, NULL))
return 0;

// Copy the BITMAPINFOHEADER and RGBQUAD array into the file. 
if(!WriteFile(hf, (LPVOID) pbih, sizeof(BITMAPINFOHEADER) + pbih->biClrUsed * sizeof (RGBQUAD), (LPDWORD) &dwTmp, ( NULL))) 
return 0; 

// Copy the array of color indices into the .BMP file. 
dwTotal = cb = pbih->biSizeImage; 
hp = lpBits; 
if(!WriteFile(hf, (LPSTR) hp, (int) cb, (LPDWORD) &dwTmp,NULL)) 
return 0; 

// Close the .BMP file. 
if(!CloseHandle(hf)) 
return 0; 

// Free memory. 
GlobalFree((HGLOBAL)lpBits);

return 1;
}

PBITMAPINFO CreateBitmapInfoStruct(HBITMAP hBmp)
{ 
BITMAP bmp; 
PBITMAPINFO pbmi; 
WORD cClrBits;
// Retrieve the bitmap color format, width, and height. 
if (!GetObject(hBmp, sizeof(BITMAP), (LPSTR)&bmp)) 
return NULL;

// Convert the color format to a count of bits. 
cClrBits = (WORD)(bmp.bmPlanes * bmp.bmBitsPixel); 
if (cClrBits == 1) 
cClrBits = 1; 
else if (cClrBits <= 4) 
cClrBits = 4; 
else if (cClrBits <= 8) 
cClrBits = 8; 
else if (cClrBits <= 16) 
cClrBits = 16; 
else if (cClrBits <= 24) 
cClrBits = 24; 
else cClrBits = 32; 

// Allocate memory for the BITMAPINFO structure. (This structure 
// contains a BITMAPINFOHEADER structure and an array of RGBQUAD 
// data structures.) 

if (cClrBits != 24) 
pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
sizeof(BITMAPINFOHEADER) + 
sizeof(RGBQUAD) * (1<< cClrBits)); 

// There is no RGBQUAD array for the 24-bit-per-pixel format. 

else 
pbmi = (PBITMAPINFO) LocalAlloc(LPTR, 
sizeof(BITMAPINFOHEADER)); 

// Initialize the fields in the BITMAPINFO structure. 

pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 
pbmi->bmiHeader.biWidth = bmp.bmWidth; 
pbmi->bmiHeader.biHeight = bmp.bmHeight; 
pbmi->bmiHeader.biPlanes = bmp.bmPlanes; 
pbmi->bmiHeader.biBitCount = bmp.bmBitsPixel; 
if (cClrBits < 24) 
pbmi->bmiHeader.biClrUsed = (1<<cClrBits); 

// If the bitmap is not compressed, set the BI_RGB flag. 
pbmi->bmiHeader.biCompression = BI_RGB; 

// Compute the number of bytes in the array of color 
// indices and store the result in biSizeImage. 
// For Windows NT, the width must be DWORD aligned unless 
// the bitmap is RLE compressed. This example shows this. 
// For Windows 95/98/Me, the width must be WORD aligned unless the 
// bitmap is RLE compressed.
pbmi->bmiHeader.biSizeImage = ((pbmi->bmiHeader.biWidth * cClrBits +31) & ~31) /8
* pbmi->bmiHeader.biHeight; 
// Set biClrImportant to 0, indicating that all of the 
// device colors are important. 
pbmi->bmiHeader.biClrImportant = 0; 
return pbmi; 
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: