You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++使用24位RGB格式创建DDB灰度位图底部出现黑色块问题求助

问题原因

  • 核心原因是CreateCompatibleBitmap创建的位图位深度与你构造的24位RGB数据不匹配:该API会继承传入DC的位深度,当前主流系统显示位深度为32位,你按24位长度传入像素数据,总数据量不足32位位图的要求,导致底部区域像素没有被赋值,出现黑块。
  • 隐含问题:你在WM_PAINT中反复创建HBITMAP对象,未释放前一次创建的对象,会造成GDI资源泄漏,运行时间过长会导致界面绘制异常。
  • 通用隐患:GDI位图要求每行像素数据长度必须为4字节的整数倍,你当前1024宽度刚好满足1024*3=3072是4的倍数,若更换其他宽度也会出现绘制异常。

解决方案

推荐使用CreateDIBSection创建指定格式的DIB位图,完全可控像素数据格式,不会出现位深度不匹配的问题,修改后的关键代码如下:

1. 变量定义修改

// WndProc内的静态变量修改为:
static HBITMAP hBitmap = NULL;
static BYTE* lpBits = NULL;

2. WM_CREATE逻辑修改

case WM_CREATE:
{
    // 定义24位RGB位图信息头
    BITMAPINFO bmi = {0};
    bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    bmi.bmiHeader.biWidth = 1024;
    // 高度设为负数表示位图是顶行向下的布局,和你填充数据的顺序一致,无需坐标翻转
    bmi.bmiHeader.biHeight = -408;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 24;
    bmi.bmiHeader.biCompression = BI_RGB;

    HDC hdc = GetDC(hWnd);
    // 创建DIB位图,直接获取像素缓冲区指针
    hBitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void**)&lpBits, NULL, 0);
    ReleaseDC(hWnd, hdc);

    int grayVal = 0;
    // 计算行步长,保证4字节对齐
    int rowStride = (1024 * 3 + 3) / 4 * 4;
    for (int y = 0; y < 408; y++)
    {
        BYTE* pRow = lpBits + y * rowStride;
        for (int x = 0; x < 1024; x++)
        {
            // 24位位图存储顺序为B、G、R
            pRow[x * 3 + 0] = grayVal;
            pRow[x * 3 + 1] = grayVal;
            pRow[x * 3 + 2] = grayVal;
        }
        grayVal++;
        if (grayVal > 255) grayVal = 0;
    }
    break;
}

3. WM_PAINT逻辑修改

case WM_PAINT:
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hWnd, &ps);
    RECT clientRect;
    GetClientRect(hWnd, &clientRect);

    HDC hdcMem = CreateCompatibleDC(hdc);
    HBITMAP hOldBmp = (HBITMAP)SelectObject(hdcMem, hBitmap);
    StretchBlt(hdc, clientRect.left, clientRect.top, clientRect.right, clientRect.bottom,
        hdcMem, 0, 0, 1024, 408, SRCCOPY);
    // 选回原有位图,避免资源泄漏
    SelectObject(hdcMem, hOldBmp);
    DeleteDC(hdcMem);

    EndPaint(hWnd, &ps);
    break;
}

4. 资源释放逻辑保持即可

WM_DESTROY中调用DeleteObject(hBitmap)即可,CreateDIBSection分配的像素缓冲区会随位图对象一起释放,无需手动释放。

内容的提问来源于stack exchange,提问作者Brian Bai

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 22:09:02