Thanks for the replies
>In both these cases, you're not counting pixels
The code I put up was simplified, because I didn't expect people to read through reems of the stuff & made the mistake in the simplification. I've pasted my more complete code below.
>Unfortunately, the bitmap functions seem not to call SetLastError()
That's helpful. Thanks. It saves me wasting time trying to figure out why there is no error.
>You'd have to tell us that. It is true that the bitmap can't be selected into any DC when you call GetDiBits().
I'm not sure because the HBITMAP I am using is coming from a third-party control (TBitmap if that helps). But I think that is where the problem is. Is there any way I could unselect a HBITMAP from a device context?
I have in fact read the manual, but still gotta admit I'm not 100% sure about device contexts. For example, I am calling CreateCompatibleDC(0) to a device of the screen. Is this what I should be doing?
int Gfx::create(Gfx& dst, void* src, int cnt, int y)
// Creates gfx data and fills it with contents of bitmap from
// platform specific bitmap object src. At the moment, this method
// only works under windows. Does nothing under any other platform.
// Under windows, src is a HBITMAP & hdSrc is a HDC.
// Gfx memory data which must be destroyed when finished by calling
// destroy(). cnt is number of rows to retrieve. If this is <= 0,
// full bmp height is retrieved. y is row to scan from which defaults
// to zero if omitted. hdSrc maybe null, in which case screen is used.
// If this method fails, rslt.data is NULL(0) & returns
// platform specific error code. Error is -1 if operation
// is not supported on platform.
if (y < 0) y = 0;
// Ensure existing is destroyed.
// WINDOWS IMPLEMENTATION
// hndl must not be 'selected into a device'
err = 0;
HDC hdc = 0;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// Make temporary compatible device
hdc = CreateCompatibleDC(0);
// Get dimensions first
GetDIBits(hdc, (HBITMAP)src, 0, 0, 0, &bmi, DIB_RGB_COLORS);
// We always want positive height (bottom up bmp)
bmi.bmiHeader.biHeight = abs(bmi.bmiHeader.biHeight);
// Work out full size count if needed
if (cnt <= 0) cnt = bmi.bmiHeader.biHeight - y;
// Fill data
dst.pDim.x = bmi.bmiHeader.biWidth;
dst.pDim.y = cnt;
// Check we can handle range
err = ERROR_INVALID_PARAMETER;
if (y + cnt <= bmi.bmiHeader.biHeight && cnt > 0)
// Set pixel format to be retrieved
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;
unsigned int sz = dst.rowsz() * dst.pDim.y;
if (sz > 0)
// Create memory array
dst.pData = new char[sz];
err = 0;
if (GetDIBits(hdc, (HBITMAP)src, (WORD)y, (WORD)cnt, dst.pData,
&bmi, DIB_RGB_COLORS) == 0)
// Error - destroy memory and
// error code will be set below
ShowMessage("Y " + IntToStr(y));
ShowMessage("CNT : " +IntToStr(cnt));
throw Exception("Error " + IntToStr(GetLastError()));
// If no data - set error code
if (dst.pData == 0)
dst.pDim = Axy();
if (err == 0) err = GetLastError();
// Free temporary device context
// NOT SUPPORTED
err = -1;