I want move a buffer of color values to a window using BitBlt
, only the window shows up empty. When I compile and run the code from How can I load a bitmap inside my window? (with my own example .bmp file), the window also shows up empty.
After some testing, the problem appears to be with SelectObject()
. According to the documentation, when the return value is NULL an error has occered: https://learn.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-selectobject. The return value is NULL, but GetLastError()
gives 0, indicating there has not been an error. What is the problem here?
case WM_CREATE:
std::fill(arr, arr + sizeof(arr), RGB(255,0,0));
hBitmap = CreateBitmap(240, 120, 1, sizeof(COLORREF), (void*) arr);
UpdateWindow(hwnd);
break;
case WM_PAINT:
PAINTSTRUCT ps;
BITMAP bitmap;
HGDIOBJ oldBitmap;
HDC hdcMem;
HDC hdc;
hdc = BeginPaint(hwnd, &ps);
hdcMem = CreateCompatibleDC(hdc);
oldBitmap = SelectObject(hdcMem, hBitmap);
std::cout << (oldBitmap == NULL) << std::endl;
std::cout << GetLastError();
GetObject(hBitmap, sizeof(bitmap), &bitmap);
BitBlt(hdc, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);
SelectObject(hdcMem, oldBitmap);
DeleteDC(hdcMem);
EndPaint(hwnd, &ps);
break;
(BTW: I use main()
instead of WinMain()
and GetModuleHandle(NULL)
each time I need the hInstance
. As the window functions fine, I suspect it has nothing to do with this, but I'll mention it anyway.)
---SOLVED!---
I've got it working now :) For others seeing this, this is what I've changed:
case WM_CREATE:
std::fill(arr, arr + 240 * 120, RGB(255,0,0));
hBitmap = CreateBitmap(240, 120, 1, sizeof(COLORREF) * 8, (void*) arr);
UpdateWindow(hwnd);
break;
If arr
is a pointer, use the total number of elements (240 * 120
)
If arr
is an array, sizeof
will return the total size in bytes. Instead use sizeof(arr)/sizeof(*arr)
to find the count of array (total number of array's elements, or total number of pixels). For example, assuming arr
's element is 32-bit, then you are looking at 240 * 120
pixels, where each pixel is 4 bytes or 32 bits.
CreateBitmap
's 4th parameter expects the size in bits, so it should be sizeof(*arr) * 8
or just 32.
uint32_t arr[240 * 120];
std::fill(arr, arr + sizeof(arr)/sizeof(*arr), RGB(255, 0, 0));
//or std::fill(arr, arr + 240 * 120, RGB(255, 0, 0));
hBitmap = CreateBitmap(240, 120, 1, 32, (void*)arr);
Note that this will produce a blue bitmap, not red, because it is using BGR format instead of RGB.
It appears you already know how to use memory dc. You can create a bitmap with CreateCompatibleBitmap
, then select that bitmap in to memory dc, and use the standard GDI functions such as FillRect
. This will avoid the pitfalls with counting the bits and bytes.