Как я могу отобразить растровое изображение (массив со значениями цвета) в окне, используя Window API? - PullRequest
1 голос
/ 20 мая 2019

Я хочу переместить буфер значений цвета в окно, используя BitBlt, только окно отображается пустым. Когда я компилирую и запускаю код из Как я могу загрузить растровое изображение в моем окне? (с моим собственным примером файла .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 Ответ

2 голосов
/ 21 мая 2019

Если 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);

Обратите внимание, что при этом будет получено голубое растровое изображение, а не красное, потому что вместо формата RGB используется формат BGR.

Похоже, вы уже знаете, как использовать память постоянного тока.Вы можете создать растровое изображение с помощью CreateCompatibleBitmap, затем выбрать это растровое изображение в памяти постоянного тока и использовать стандартные функции GDI, такие как FillRect.Это позволит избежать ошибок при подсчете битов и байтов.

...