Windows 7 - MSDN Example GDI_CapturingAnImage.cpp BMP Bug?

Asked By dwb on 13-Oct-09 05:40 PM
Does the example code for "Capturing an Image"
http://msdn.microsoft.com/en-us/library/dd183402(VS.85).aspx have a bug or is
it just me? To get the CaptureAnImage() function to run you will have to call
it from somewhere, e.g. like when a key is pressed:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
lParam)
...
case WM_CHAR:
CaptureAnImage(hWnd);
break;

It looks okay in the window but the .bmp file looks wrong. The first 10
pixels of the left edge are on the right one pixel down. The internal
BITMAPFILEHEADER.bfSize does not match the actual file size, but is 14 bytes
less. If a bug, how can it be fixed?

Visual Studio 2008 Version 9.0.30729.1 SP




dwb replied to dwb on 15-Oct-09 11:19 AM
Improvements were incorporated there on build date 10/9/2009.
dwb replied to dwb on 15-Oct-09 12:07 PM
It seems to work if this code...:

HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize+sizeof(BITMAPINFOHEADER));
LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDIB);
*lpbi = bi;

// Gets the "bits" from the bitmap and copies them into a buffer
// which is pointed to by lpbi
GetDIBits(hdcWindow,hbmScreen,0,
(UINT)bmpScreen.bmHeight,
lpbi,
(BITMAPINFO *)lpbi, DIB_RGB_COLORS);
...
WriteFile(hFile,(LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER),
&dwBytesWritten, NULL);
WriteFile(hFile,(LPSTR)lpbi,dwSizeofDIB,&dwBytesWritten,NULL);

...is replaced by this code:

HANDLE hDIB = GlobalAlloc(GHND,dwBmpSize);
LPVOID lpv = GlobalLock(hDIB);

// Gets the "bits" from the bitmap and copies them into a buffer
// which is pointed to by lpv
GetDIBits(hdcWindow,hbmScreen,0,
(UINT)bmpScreen.bmHeight,
lpv,
(BITMAPINFO *)&bi, DIB_RGB_COLORS);

// A file is created, this is where we will save the screen capture.
HANDLE hFile = CreateFile(L"captureqwsx.bmp",
GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL ,NULL);

// Add the size of the headers to the size of the bitmap to get the
total file size
DWORD dwSizeofDIB   =    dwBmpSize + sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER);

//Offset to where the actual bitmap bits start.
bmfHeader.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
(DWORD)sizeof(BITMAPINFOHEADER);

//Clear reserved bytes
bmfHeader.bfReserved1 = 0;
bmfHeader.bfReserved2 = 0;

//Size of the file
bmfHeader.bfSize = dwSizeofDIB;

//bfType must always be BM for Bitmaps
bmfHeader.bfType = 0x4D42; //BM

DWORD dwBytesWritten;
WriteFile(hFile,(LPSTR)&bmfHeader, sizeof(BITMAPFILEHEADER),
&dwBytesWritten, NULL);
WriteFile(hFile,(LPSTR)&bi,sizeof(bi),&dwBytesWritten,NULL);
WriteFile(hFile,(LPSTR)lpv,dwBmpSize,&dwBytesWritten,NULL);