The method GetScreenBitmap() is used to capture the screen.
There are some redundant operations performed in the method, which u can ignore or modify....
#define DibWidth(pDib) (((BITMAPINFOHEADER *)pDib)->biWidth)
#define DibHeight(pDib) (((BITMAPINFOHEADER *)pDib)->biHeight)
#define DibBitCount(pDib) (((BITMAPINFOHEADER *)pDib)->biBitCount)
#define DibClrUsed(pDib) (((BITMAPINFOHEADER *)pDib)->biClrUsed)
#define DibNumColors(pDib) (DibClrUsed(pDib) ? DibClrUsed (pDib) : (DibBitCount(pDib) <= 8 ? 1 << DibBitCount(pDib) : 0))
#define DibClrTablePtr(pDib) ((RGBQUAD *) (pDib + sizeof (BITMAPINFOHEADER)))
#define DibBitsPtr(pDib) (pDib + sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * DibNumColors(pDib))
#define DibRowLength(pDib) (((DibWidth(pDib) * DibBitCount(pDib) + 31) & ~31) >> 3)
#define DibRowPtr(pDib,iRow) (DibBitsPtr(pDib) + DibRowLength(pDib) * (DibHeight(pDib) - (iRow) - 1))
#define DibPixelPtr(pDib,iRow,iCol) (DibRowPtr(pDib,iRow) + (iCol) * DibBitCount(pDib) / 8)
#define DibBitsSize(pDib) (DibHeight(pDib) * DibRowLength(pDib))
#define DibTotalSize(pDib) (sizeof (BITMAPINFOHEADER) + sizeof (RGBQUAD) * DibNumColors(pDib) + DibBitsSize(pDib))
#define DibGetColor(pDib,i) (* (DibClrTablePtr(pDib) + (i)))
#define DibSetColor(pDib,i,rgb) (* (DibClrTablePtr(pDib) + (i)) = (rgb))
//Get the Screen Bitmap and return a global handle to the memory containing the bmp
BOOL GetScreenBitmap(HDC appDC);
HPALETTE GetCurrentPalette (HWND hwnd);
BYTE * ConvertDDBtoDIB (HWND hwnd, HBITMAP hBitmap, HPALETTE hPalette);
int Compare1 (const void * p1, const void * p2) ;
int Compare2 (const void * p1, const void * p2) ;
typedef struct
{
int indexOld ; // The original palette index
int indexNew ; // The new palette index
DWORD dwCount ; // The number of pixels of that color
RGBQUAD rgb ; // The RGB value for that index
}
COLORCOUNT ;
BYTE * DibSortColorTable (BYTE * pDib);
DWORD DibGetPixel (PBYTE pDib, int iRow, int iCol) ;
void DibSetPixel (PBYTE pDib, int iRow, int iCol, DWORD dwPixel) ;
//Get the Screen Bitmap and return a global handle to the memory containing the bmp
BOOL
GetScreenBitmap(HDC hdcscr)
{
HPALETTE hPalette;
BYTE * pdib;
RECT appRectNew;
BITMAPFILEHEADER bmfh ;
DWORD dwTotalSize, dwBitsSize ;
GetClientRect(hWndApp, &appRectNew);
if(appRectNew.bottom + 48 != appRect.bottom ||
appRectNew.right + 8 != appRect.right ||
appRectNew.top != appRect.top ||
appRectNew.left != appRect.left)
{
appRect.bottom = appRectNew.bottom + 48;
appRect.right = appRectNew.right + 8;
appRect.top = appRectNew.top;
appRect.left = appRectNew.left;
//
hbitmap = CreateCompatibleBitmap(hdcscr,
int (appRect.right - appRect.left),
int (appRect.bottom - appRect.top));
SelectObject(hdcmem, hbitmap);
if(hbitmap == NULL)
{
//error
//err1 = GetLastError();
}
}
BitBlt(hdcmem, 0, 0,
abs(appRect.right - appRect.left),
abs(appRect.bottom - appRect.top),
hdcscr, appRect.left, appRect.top, SRCCOPY );
hPalette = GetCurrentPalette(hWndApp);
//if(hPalette == NULL)
if(hbitmap)
{
pdib = ConvertDDBtoDIB(hWndApp, hbitmap, hPalette);
if(pdib == NULL)
{
return 0;
}
pdib = DibSortColorTable(pdib);
}
// Get the size of the DIB and the bits
dwBitsSize = DibBitsSize (pdib) ;
dwTotalSize = DibTotalSize (pdib) ;
// Now we're ready to define the BITMAPFILEHEADER
bmfh.bfType = * (WORD *) "BM" ;
bmfh.bfSize = sizeof (BITMAPFILEHEADER) + dwTotalSize ;
bmfh.bfReserved1 = 0 ;
bmfh.bfReserved2 = 0 ;
bmfh.bfOffBits = bmfh.bfSize - dwBitsSize ;
//Allocate memory and move the bitmap data to the memory
if(prevMemScreenDataSize == 0 || prevMemScreenDataSize != bmfh.bfSize
|| memScreenData == 0)
memScreenData = (LPBYTE) GlobalAlloc(GMEM_FIXED, bmfh.bfSize);
memcpy((void *)memScreenData,(LPVOID)&bmfh, sizeof (bmfh));
memcpy((void *)(memScreenData + sizeof(bmfh)),(LPVOID)pdib, dwTotalSize);
//DeleteObject(hPalette);
//set the buffer size and the Buffer pointer
memScreenDataSize = bmfh.bfSize;
screenInfoCard->bufSize = bmfh.bfSize;
screenInfoCard->hSize = appRect.right - appRect.left;
screenInfoCard->vSize = appRect.bottom - appRect.top;
prevMemScreenDataSize = bmfh.bfSize;
// Open the output file
//write the bmp into the memory
DWORD dwTemp =0;
HANDLE hf = CreateFile("testCaptureBitmap.bmp",
GENERIC_READ | GENERIC_WRITE,
(DWORD) 0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
(HANDLE) NULL);
WriteFile(hf, memScreenData, bmfh.bfSize,
(LPDWORD) &dwTemp, NULL);
CloseHandle(hf);
free(pdib);
return true;
}
/*-------------------------------------------------------
GetCurrentPalette: Obtains the current system palette.
-------------------------------------------------------*/
HPALETTE GetCurrentPalette (HWND hwnd)
{
HDC hdc ;
HPALETTE hPalette ;
int iSize ;
LOGPALETTE * plogpal ;
// Get a video device context
hdc = GetDC (hwnd) ;
// If the video device supports palettes, get palette size
// (Betcha a hundred to one it'll be 256!)
if (RC_PALETTE & GetDeviceCaps (hdc, RASTERCAPS))
{
iSize = GetDeviceCaps (hdc, SIZEPALETTE) ;
// Allocate memory for the palette and get it.
plogpal = (LOGPALETTE*)malloc (sizeof (LOGPALETTE) +
sizeof (PALETTEENTRY) * (iSize - 1)) ;
plogpal->palVersion = 0x0300 ;
plogpal->palNumEntries = iSize ;
GetSystemPaletteEntries (hdc, 0, iSize, plogpal->palPalEntry) ;
// Now create a palette based on the system palette entries
hPalette = CreatePalette (plogpal) ;
// free the memory
free (plogpal) ;
}
// If the device doesn't support palettes, hPalette is NULL.
else
hPalette = NULL ;
// Release the DC
ReleaseDC (hwnd, hdc) ;
return hPalette ;
}
/*-------------------------------------------------------------------------
ConvertDDBtoDIB: Converts a GDI bitmap object to a DIB using a palette.
Function based on Knowledge Base article Q80080.
-------------------------------------------------------------------------*/
BYTE * ConvertDDBtoDIB (HWND hwnd, HBITMAP hBitmap, HPALETTE hPalette)
{
BITMAP bm ;
BITMAPINFO * pbmi ;
BYTE * pBits ;
HDC hdc ;
WORD wBitCount, wNumColor, wColorEntries, wRowLength ;
// Get information about the DDB & calculate bits per pixel
GetObject (hBitmap, sizeof (BITMAP), (PSTR) &bm) ;
wBitCount = bm.bmPlanes * bm.bmBitsPixel ;
// Figure out the DIB bit count and number of colors.
// (Probably more generalized than it needs to be)
if (wBitCount > 16)
{
wNumColor = 0 ;
wBitCount = 24 ;
}
else if (wBitCount > 8)
{
wNumColor = 0 ;
wBitCount = 16 ;
}
else if (wBitCount > 4)
{
wNumColor = 1 << wBitCount ;
wBitCount = 8 ;
}
else if (wBitCount > 2)
{
wNumColor = 1 << wBitCount ;
wBitCount = 4 ;
}
else if (wBitCount == 1)
{
wNumColor = 2 ;
}
// Determine the number of entries in the DIB color table
wColorEntries = wNumColor ;
if (wColorEntries == 0 && wBitCount <= 8)
wColorEntries = 1 << wBitCount ;
// DIB rows are always multiple of 4 bytes long.
wRowLength = ((bm.bmWidth * wBitCount + 31) & ~31) >> 3 ;
// Allocate memory for the entire DIB.
DWORD size = sizeof (BITMAPINFOHEADER) +
sizeof (RGBQUAD) * wColorEntries +
wRowLength * bm.bmHeight;
pbmi = (BITMAPINFO*)malloc (size) ;
if (pbmi == NULL)
{
cout << "ERROR:" << GetLastError() << endl;
return NULL ;
}
// Initialize the BITMAPINFOHEADER
pbmi->bmiHeader.biSize = sizeof (BITMAPINFOHEADER) ;
pbmi->bmiHeader.biWidth = bm.bmWidth ;
pbmi->bmiHeader.biHeight = bm.bmHeight ;
pbmi->bmiHeader.biPlanes = 1 ;
pbmi->bmiHeader.biBitCount = wBitCount ;
pbmi->bmiHeader.biCompression = BI_RGB ;
pbmi->bmiHeader.biSizeImage = 0 ;
pbmi->bmiHeader.biXPelsPerMeter = 0 ;
pbmi->bmiHeader.biYPelsPerMeter = 0 ;
pbmi->bmiHeader.biClrUsed = wNumColor ;
pbmi->bmiHeader.biClrImportant = 0 ;
// Determine the address of the pixel bits in the DIB
pBits = (BYTE *) pbmi + sizeof (BITMAPINFOHEADER) +
sizeof (RGBQUAD) * wColorEntries ;
// Get a video device context and select the palette into it
hdc = GetDC (hwnd) ;
SelectPalette (hdc, hPalette, FALSE) ;
RealizePalette (hdc) ;
// Here's the function we've all been waiting for.
GetDIBits (hdc, hBitmap, 0, bm.bmHeight, pBits, pbmi, DIB_RGB_COLORS) ;
// Clean up and get out.
ReleaseDC (hwnd, hdc) ;
return (BYTE *) pbmi ;
}
// Sorts the array of COLORCOUNT structures to put the highest
// counts at the beginning.
int Compare1 (const void * p1, const void * p2)
{
COLORCOUNT * pcc1 = (COLORCOUNT *) p1 ;
COLORCOUNT * pcc2 = (COLORCOUNT *) p2 ;
if (pcc1->dwCount > pcc2->dwCount)
return -1 ;
return (pcc1->dwCount < pcc2->dwCount) ;
}
// Sorts the array of COLORCOUNT structures to put the lowest
// old index at the beginning.
int Compare2 (const void * p1, const void * p2)
{
COLORCOUNT * pcc1 = (COLORCOUNT *) p1 ;
COLORCOUNT * pcc2 = (COLORCOUNT *) p2 ;
if (pcc1->indexOld < pcc2->indexOld)
return -1 ;
return (pcc1->indexOld > pcc2->indexOld) ;
}
/*----------------------------------------------------------------------
DibSortColorTable: Sorts a DIB color table to put most-used colors
at the beginning. Possibly reduces size of DIB
for unused colors, so returns pointer to new DIB.
----------------------------------------------------------------------*/
BYTE * DibSortColorTable (BYTE * pDib)
{
COLORCOUNT cc[256] ;
int cRows, cCols, cClrs, iRow, iCol, i, cClrsNew ;
// This function is only applicable for palette DIBs
if (DibBitCount(pDib) > 8)
return pDib ;
// Get some useful information about the DIB using macros
// defined in ScreenSeizeDib.h
cRows = DibHeight (pDib) ;
cCols = DibWidth (pDib) ;
cClrs = DibNumColors (pDib) ;
// Initialize the structure with DIB color table
for (i = 0 ; i < cClrs ; i++)
{
cc.indexOld = i ;
cc.indexNew = 0 ;
cc.dwCount = 0 ;
cc.rgb = DibGetColor (pDib, i) ;
}
// Now accumulate the pixel counts in the structure
for (iRow = 0 ; iRow < cRows ; iRow++)
for (iCol = 0 ; iCol < cCols ; iCol++)
cc[DibGetPixel (pDib, iRow, iCol)].dwCount ++ ;
// Sort the structure by the pixel counts
qsort (&cc, cClrs, sizeof (COLORCOUNT), Compare1) ;
// Transfer the sorted colors into the DIB, but
// don't transfer those that aren't used at all.
for (i = 0 ; i < cClrs && cc.dwCount ; i++)
DibSetColor (pDib, i, cc.rgb) ;
// The new number of colors is now available
cClrsNew = i ;
// Put the new color indices into the structure
for (i = 0 ; i < cClrs ; i++)
cc.indexNew = i ;
// Sort the structure by the old indices
qsort (&cc, cClrs, sizeof (COLORCOUNT), Compare2) ;
// Now we can easily change each color index
for (iRow = 0 ; iRow < cRows ; iRow++)
for (iCol = 0 ; iCol < cCols ; iCol++)
DibSetPixel (pDib, iRow, iCol,
cc[DibGetPixel (pDib, iRow, iCol)].indexNew) ;
// Now the file can be tightened up to get rid of unused colors
if (cClrsNew < cClrs)
{
BYTE * pBitsOld, * pBitsNew ;
int iBitsSize ;
pBitsOld = DibBitsPtr (pDib) ;
((BITMAPINFOHEADER *) pDib)->biClrUsed = cClrsNew ;
pBitsNew = DibBitsPtr (pDib) ;
iBitsSize = DibBitsSize (pDib) ;
for (i = 0 ; i < iBitsSize ; i++)
*pBitsNew++ = *pBitsOld++ ;
pDib = (BYTE*)realloc (pDib, DibTotalSize (pDib)) ;
}
return pDib ;
}
/*--------------------------------------------------------------------------
DibGetPixel: Gets a pixel value for a particular row and column address.
NOTE: No bounds check on row and column!
--------------------------------------------------------------------------*/
DWORD DibGetPixel (PBYTE pDib, int iRow, int iCol)
{
// Handy macro in ScreenSeizeDib.h
BYTE * pPixel = DibPixelPtr (pDib, iRow, iCol) ;
// Another macro and gritty bit work
switch (DibBitCount (pDib))
{
case 1: return 0x01 & (* pPixel >> (7 - (iCol & 7))) ;
case 4: return 0x0F & (* pPixel >> (iCol & 1 ? 0 : 4)) ;
case 8: return * pPixel ;
case 16: return * (WORD *) pPixel ;
case 24: return 0x00FFFFFF & * (DWORD *) pPixel ;
case 32: return * (DWORD *) pPixel ;
}
return 0 ;
}
/*--------------------------------------------------------------------------
DibSetPixel: Sets a pixel value for a particular row and column address.
NOTE: No bounds check on row and column!
--------------------------------------------------------------------------*/
void DibSetPixel (PBYTE pDib, int iRow, int iCol, DWORD dwPixel)
{
// Ditto
BYTE * pPixel = DibPixelPtr (pDib, iRow, iCol) ;
switch (DibBitCount (pDib))
{
case 1: * pPixel &= ~(1 << (7 - (iCol & 7))) ;
* pPixel |= dwPixel << (7 - (iCol & 7)) ;
break ;
case 4: * pPixel &= 0x0F << (iCol & 1 ? 4 : 0) ;
* pPixel |= dwPixel << (iCol & 1 ? 0 : 4) ;
break ;
case 8: * pPixel = (BYTE) dwPixel ;
break ;
case 16: * (WORD *) pPixel = (WORD) dwPixel ;
break ;
case 24: * (RGBTRIPLE *) pPixel = * (RGBTRIPLE *) &dwPixel ;
break ;
case 32: * (DWORD *) pPixel = dwPixel ;
break ;
}
}