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

a64a0gku  于 2023-07-01  发布在  其他
关注(0)|答案(2)|浏览(185)

我想用BitBlt把一个颜色值的缓冲区移到一个窗口中,只有窗口显示为空。当我从How can I load a bitmap inside my window?编译并运行代码时(使用我自己的示例.bmp文件),窗口也显示为空。
经过一些测试,问题似乎与SelectObject()有关。根据文档,当返回值为NULL时,会发生错误:https://learn.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;

(BTW:每次需要hInstance时,我都使用main()而不是WinMain()GetModuleHandle(NULL)。由于窗口功能正常,我怀疑它与此无关,但无论如何我都会提到它。)

  • 解决了!-
    我现在已经让它工作了:)对于其他人看到这一点,这是我所做的改变:
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;
daolsyd0

daolsyd01#

C++类below允许使用CreateBitmap函数轻松创建位图。

[创建位图的步骤]

1.分配所需尺寸的ColorU像素阵列。
1.使用CreateBitmap函数创建位图。

[示例]

在示例中,为了简单起见,省略了错误检查。

// pixel array dimensions
const int32_t width = 720, height = 480;

ColorU *pixelArray = new ColorU[width * height]();
for (size_t i = 0; i < width * height; i++) {
    pixelArray[i].setColor(ColorU::Blue);
}

// assume "window" is valid window handle
RECT client = GetWindowRect(window, &rect);
// assume "windowDC" is valid window DC
HDC tempDC = CreateCompatibleDC(windowDC);
HBITMAP bitmap = CreateBitmap(width, height, 1, 32, pixelArray);
HGDIOBJ obj = SelectObject(tempDC, bitmap);
BitBlt(consoleDC, 0, 0,
    client.right - client.left,
    client.bottom - client.top,
    tempDC, 0, 0, SRCCOPY);
SelectObject(tempDC, obj);
DeleteDC(tempDC);
DeleteObject(bitmap);

delete[] pixelArray;

vv ColorU vv

#ifndef _COLOR_U_H_
#define _COLOR_U_H_

#include <stdint.h>

#ifndef _MINWINDEF_
using BYTE = uint8_t;
using WORD = uint16_t;
using DWORD = uint32_t;
using FLOAT = float;
#endif // !_MINWINDEF_
#ifndef _WINDEF_
using COLORREF = DWORD;
#endif // !_WINNT

#pragma pack(push, 1)

#pragma warning(disable:4005)
#define RGB(r, g, b) (COLORREF)(((BYTE)(r))|(((WORD)((BYTE)(g)))<<8)|(((DWORD)((BYTE)(b)))<<16))
#define GetRValue(rgb) (BYTE)((DWORD)(rgb))
#define GetGValue(rgb) (BYTE)(((WORD)((DWORD)(rgb)))>>8)
#define GetBValue(rgb) (BYTE)(((DWORD)(rgb))>>16)
#pragma warning(default:4005)

// ----------------------------------------------------------------
// Class "ColorU"
// - This Class Provides GDI Compatible Color Manipulations
// Color Format
// - BBGGRRXX: [ Blue:BYTE, Green:BYTE, Red:BYTE, Reserved:BYTE ]
// ----------------------------------------------------------------
class ColorU {
public:
    
    enum KnownColor : COLORREF {
        
        White = RGB(191, 191, 191),
        Gray = RGB(89, 89, 89),
        
        BrightWhite = RGB(255, 255, 255),
        Black = RGB(0, 0, 0),
        
        Red = RGB(255, 0, 0),
        Green = RGB(0, 255, 0),
        Blue = RGB(0, 0, 255),
        
        LightRed = RGB(255, 128, 128),
        LightGreen = RGB(128, 255, 128),
        LightBlue = RGB(128, 128, 255),
        
        DarkRed = RGB(128, 0, 0),
        DarkGreen = RGB(0, 128, 0),
        DarkBlue = RGB(0, 0, 128),
        
        Aqua = RGB(0, 191, 255),
        Purple = RGB(191, 0, 255),
        Yellow = RGB(255, 191, 0),
        
        LightAqua = RGB(0, 255, 255),
        LightPurple = RGB(255, 0, 255),
        LightYellow = RGB(255, 255, 0)
        
    };
    
    enum class Component : BYTE {
        Blue, Green, Red
    };
    
    // ----------------------------------------
    // constructors
    
    ColorU() noexcept {
        m_blue = 0x00;
        m_green = 0x00;
        m_red = 0x00;
        m_reserved = 0x00;
    }
    
    ColorU(KnownColor knownColor) noexcept {
        m_blue = GetBValue(knownColor);
        m_green = GetGValue(knownColor);
        m_red = GetRValue(knownColor);
        m_reserved = 0x00;
    }

    explicit ColorU(BYTE red, BYTE green, BYTE blue) noexcept {
        m_blue = blue;
        m_green = green;
        m_red = red;
        m_reserved = 0x00;
    }

    ColorU(COLORREF rgbColor) noexcept {
        m_blue = GetBValue(rgbColor);
        m_green = GetGValue(rgbColor);
        m_red = GetRValue(rgbColor);
        m_reserved = 0x00;
    }

    explicit ColorU(FLOAT red, FLOAT green, FLOAT blue) noexcept {
        m_blue = blue <= 0.0F ? 0 : blue >= 1.0F ? 255 : (BYTE)(blue * 255);
        m_green = green <= 0.0F ? 0 : green >= 1.0F ? 255 : (BYTE)(green * 255);
        m_red = red <= 0.0F ? 0 : red >= 1.0F ? 255 : (BYTE)(red * 255);
        m_reserved = 0x00;
    }
    
    // ----------------------------------------
    
    // copy constructor
    ColorU(const ColorU &other) noexcept = default;
    // copy assigment operator
    ColorU& operator=(const ColorU &other) noexcept = default;
    
    // ----------------------------------------
    // setters
    
    void setColor(KnownColor knownColor) noexcept {
        m_blue = GetBValue(knownColor);
        m_green = GetGValue(knownColor);
        m_red = GetRValue(knownColor);
    }
    
    void setColor(BYTE red, BYTE green, BYTE blue) noexcept {
        m_blue = blue;
        m_green = green;
        m_red = red;
    }
    
    void setColor(COLORREF rgbColor) noexcept {
        m_blue = GetBValue(rgbColor);
        m_green = GetGValue(rgbColor);
        m_red = GetRValue(rgbColor);
    }
    
    void setColor(FLOAT red, FLOAT green, FLOAT blue) noexcept {
        m_blue = blue <= 0.0F ? 0 : blue >= 1.0F ? 255 : (BYTE)(blue * 255);
        m_green = green <= 0.0F ? 0 : green >= 1.0F ? 255 : (BYTE)(green * 255);
        m_red = red <= 0.0F ? 0 : red >= 1.0F ? 255 : (BYTE)(red * 255);
    }
    
    // ----------------------------------------
    
    void setXValue(Component component, BYTE value) noexcept {

        switch (component) {
        case Component::Blue:
            m_blue = value;
            break;
        case Component::Green:
            m_green = value;
            break;
        case Component::Red:
            m_red = value;
            break;
        }

    }
    
    BYTE getXValue(Component component) const noexcept {
        
        switch (component) {
        case Component::Blue:
            return m_blue;
        case Component::Green:
            return m_green;
        case Component::Red:
            return m_red;
        default:
            return 0U;
        }

    }
    
    bool equal(const ColorU &other) const noexcept {
        return (
            m_blue == other.m_blue &&
            m_green == other.m_green &&
            m_red == other.m_red
        );
    }
    
    bool operator==(const ColorU &other) const noexcept {
        return equal(other);
    }
    
    bool operator!=(const ColorU &other) const noexcept {
        return !equal(other);
    }

    // ----------------------------------------
    // getters
    
    COLORREF data() const noexcept {
        return RGB(m_red, m_green, m_blue);
    }
    
    operator COLORREF() const noexcept {
        return RGB(m_red, m_green, m_blue);
    }

    // ----------------------------------------
    
    // default destructor
    ~ColorU() noexcept = default;
    
private:
    
    BYTE m_blue;
    BYTE m_green;
    BYTE m_red;
    BYTE m_reserved;
    
};

#pragma pack(pop)

#endif // !_COLOR_U_H_
mbyulnm0

mbyulnm02#

如果arr是指针,则使用元素总数(240 * 120
如果arr是一个数组,则sizeof将返回以字节为单位的总大小。相反,使用sizeof(arr)/sizeof(*arr)来查找数组的计数(数组元素的总数,或像素的总数)。例如,假设arr的元素是32位,那么您看到的是240 * 120像素,其中每个像素是4字节或32位。
CreateBitmap的第四个参数需要的是位数大小,所以应该是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。这将避免计数位和字节的陷阱。

相关问题