如何使用 Window API 在 window 中显示位图(具有颜色值的数组)?
How can I display a bitmap (array with color values) in a window using Window API?
我想使用 BitBlt
将颜色值缓冲区移动到 window,只有 window 显示为空。当我编译 运行 来自 How can I load a bitmap inside my window? 的代码(使用我自己的示例 .bmp 文件)时,window 也显示为空。
经过一些测试,问题似乎出在 SelectObject()
。根据文档,当 return 值为 NULL 时,会发生错误:https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-selectobject。 return 值为 NULL,但 GetLastError()
给出 0,表示没有发生错误。这里有什么问题?
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;
(顺便说一句:每次我需要 hInstance
时,我都使用 main()
而不是 WinMain()
和 GetModuleHandle(NULL)
。由于 window 功能正常,我怀疑这与此无关,但我还是会提到它。)
---已解决!---
我现在已经开始工作了:)对于看到这个的其他人,这就是我所做的改变:
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;
如果arr
是指针,则使用元素总数(240 * 120
)
如果 arr
是数组,sizeof
将 return 总大小(以字节为单位)。而是使用 sizeof(arr)/sizeof(*arr)
来查找数组的计数(数组元素的总数,或像素总数)。例如,假设 arr
的元素是 32 位,那么您正在查看 240 * 120
个像素,其中每个像素是 4 个字节或 32 位。
CreateBitmap
的第 4 个参数需要以位为单位的大小,因此它应该是 sizeof(*arr) * 8
或只是 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);
请注意,这将生成蓝色位图,而不是红色位图,因为它使用的是 BGR 格式而不是 RGB。
看来你已经知道如何使用内存dc了。您可以使用 CreateCompatibleBitmap
创建位图,然后 select 将该位图放入内存 dc,并使用标准 GDI 函数,例如 FillRect
。这将避免计算位和字节的陷阱。
我想使用 BitBlt
将颜色值缓冲区移动到 window,只有 window 显示为空。当我编译 运行 来自 How can I load a bitmap inside my window? 的代码(使用我自己的示例 .bmp 文件)时,window 也显示为空。
经过一些测试,问题似乎出在 SelectObject()
。根据文档,当 return 值为 NULL 时,会发生错误:https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-selectobject。 return 值为 NULL,但 GetLastError()
给出 0,表示没有发生错误。这里有什么问题?
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;
(顺便说一句:每次我需要 hInstance
时,我都使用 main()
而不是 WinMain()
和 GetModuleHandle(NULL)
。由于 window 功能正常,我怀疑这与此无关,但我还是会提到它。)
---已解决!---
我现在已经开始工作了:)对于看到这个的其他人,这就是我所做的改变:
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;
如果arr
是指针,则使用元素总数(240 * 120
)
如果 arr
是数组,sizeof
将 return 总大小(以字节为单位)。而是使用 sizeof(arr)/sizeof(*arr)
来查找数组的计数(数组元素的总数,或像素总数)。例如,假设 arr
的元素是 32 位,那么您正在查看 240 * 120
个像素,其中每个像素是 4 个字节或 32 位。
CreateBitmap
的第 4 个参数需要以位为单位的大小,因此它应该是 sizeof(*arr) * 8
或只是 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);
请注意,这将生成蓝色位图,而不是红色位图,因为它使用的是 BGR 格式而不是 RGB。
看来你已经知道如何使用内存dc了。您可以使用 CreateCompatibleBitmap
创建位图,然后 select 将该位图放入内存 dc,并使用标准 GDI 函数,例如 FillRect
。这将避免计算位和字节的陷阱。