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

问题描述 投票:0回答:2

我想使用

BitBlt
将颜色值缓冲区移动到窗口,只有窗口显示为空。当我编译并运行如何在窗口中加载位图?(使用我自己的示例 .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;

(顺便说一句:每次我需要

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;
c++ winapi drawing
2个回答
4
投票

如果

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
。这将避免计算位和字节的陷阱。


0
投票

C++ 类波纹管允许使用

CreateBitmap
函数轻松创建位图。

创建位图的步骤

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

示例

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

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

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

// 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(windowDC, 0, 0,
    client.right - client.left,
    client.bottom - client.top,
    tempDC, 0, 0, SRCCOPY);
SelectObject(tempDC, obj);
DeleteDC(tempDC);
DeleteObject(bitmap);

delete[] pixelArray;

ColorU.h:(C++11 或更高版本)

#ifndef _COLOR_U_H_
#define _COLOR_U_H_

#include <stdint.h>

using Byte = uint8_t;
using Word = uint16_t;
using Dword = uint32_t;

using Float = float;
using Uint32 = uint32_t;

using ColorRef = Dword;

#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)

namespace Graphics {
    
    // ----------------------------------------------------------------
    // 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 Property : 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;
        }
        
        // input color component range: [0, 1]
        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;
        
        // ----------------------------------------
        // getters / 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);
        }
        
        // input color component range: [0, 1]
        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);
        }
        
        // ----------------------------------------
        
        Byte getProperty(Property property) const noexcept {

            switch (property) {
            case Property::Blue:
                return m_blue;
            case Property::Green:
                return m_green;
            case Property::Red:
                return m_red;
            default:
                return 0U;
            }

        }
        
        void setProperty(Property property, Byte value) noexcept {

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

        }
        
        // ----------------------------------------
        // hashing
        
        Uint32 hash() const noexcept {

            Uint32 hash = 47837;

            const Byte *data = (const Byte *)(this);
            Byte slidingWindow = 0x00;
            
            for (Byte i = 0; i < sizeof(ColorU) - 1; i++) {
                slidingWindow <<= 4;
                slidingWindow |= (data[i] & 0xF0) >> 4;
                hash += slidingWindow * (i + 1);
                slidingWindow <<= 4;
                slidingWindow |= (data[i] & 0x0F);
                hash += slidingWindow * (i + 1);
            }

            hash |= (hash ^ 47837) << 16;

            return hash;

        }
        
        // ----------------------------------------
        
        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);
        }
        
        // ----------------------------------------
        // conversion
        
        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_
© www.soinside.com 2019 - 2024. All rights reserved.