如何使用Window API在窗口中显示位图(带有颜色值的数组)?

时间:2019-05-20 19:04:33

标签: c++ winapi drawing

我想使用BitBlt将颜色值的缓冲区移到窗口,只有窗口显示为空。当我从How can I load a bitmap inside my window?(使用自己的示例.bmp文件)编译并运行代码时,该窗口也显示为空白。

经过一些测试,问题似乎出在SelectObject()上。根据文档,当返回值为NULL时,发生了错误:https://docs.microsoft.com/en-us/windows/desktop/api/wingdi/nf-wingdi-selectobject。返回值为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;

(顺便说一句:每次我需要main()时,我使用WinMain()而不是GetModuleHandle(NULL)hInstance。由于窗口功能正常,我怀疑它无事可做,但我还是会提到它。)

---已解决!---

我现在可以正常工作了:)对于其他人来说,这就是我所做的更改:

    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;

1 个答案:

答案 0 :(得分:2)

如果arr是指针,则使用元素总数(240 * 120

如果arr是一个数组,则sizeof将返回总大小(以字节为单位)。而是使用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创建一个位图,然后选择该位图到内存dc中,并使用标准的GDI函数,例如FillRect。这样可以避免在计算位和字节时出现陷阱。