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

为何使用Windows.h中StretchDIBits绘制位图时卡顿且出现条纹?

问题根源与修复方案

1. 像素格式不匹配(核心问题)

你设置的BITMAPINFO是24位色(biBitCount = 24),但填充像素时用unsigned int(32位)写入RGB值。24位位图每个像素占3字节(R、G、B各8位),32位是4字节(含Alpha通道),这会导致内存中像素数据错位,StretchDIBits读取时出现条纹。

修复:
将biBitCount改为32,同时确保缓冲区大小与32位像素匹配:

// 在WM_SIZE消息处理中修改
buffer_bitmap.bmiHeader.biBitCount = 32;
buffer_sizes = BitmapWidth * BitmapHeight * sizeof(unsigned int);

2. 位图参数缺失与行对齐问题

Windows GDI要求位图显式指定总字节数(biSizeImage),同时每行字节数需按4字节对齐(32位像素天然满足,无需额外处理)。缺失该参数会导致绘制时数据读取错误。

修复:
在WM_SIZE中添加biSizeImage赋值:

buffer_bitmap.bmiHeader.biSizeImage = buffer_sizes;

3. 窗口重绘逻辑错误

你的WM_PAINT消息处理为空,窗口需要重绘时(如调整大小、被遮挡恢复)不会自动刷新画面,导致绘制不全。同时主循环直接调用StretchDIBits到屏幕DC,未与系统绘制时机配合,易出现画面撕裂。

修复:

  • 在WM_PAINT中完成绘制,使用BeginPaint/EndPaint获取正确DC:
case WM_PAINT:
{
    PAINTSTRUCT ps;
    HDC hdc = BeginPaint(hwnd, &ps);
    StretchDIBits(hdc, 0, 0, ClientWidth, ClientHeight, 0, 0, BitmapWidth, BitmapHeight, buffer_memory, &buffer_bitmap, DIB_RGB_COLORS, SRCCOPY);
    EndPaint(hwnd, &ps);
}
return 0;
  • 主循环只负责更新画面数据,通过InvalidateRect触发系统重绘:
// Source.cpp主循环修改
while (running == true)
{
    if (!mywindow.windowpro())
    {
        running = false;
        continue;
    }

    mywindow.backgroundcolor(225, 225, 225);
    InvalidateRect(CreateMyWindow, NULL, FALSE); // 触发WM_PAINT

    Sleep(1); // 避免CPU占用过高
}

4. 全局变量初始化问题

myhinstance未初始化会导致窗口类注册失败,需在窗口构造函数中赋值:

window::window()
{
    myhinstance = GetModuleHandle(nullptr); // 新增初始化
    WindowClass.lpszClassName = "Game_Engine";
    // ... 其他原有代码
}

5. 全屏画面撕裂优化

全屏时刷新率更高,直接绘制易出现撕裂。通过上述WM_PAINT配合系统绘制时机的方式,可让窗口管理器自动处理同步,避免撕裂。


内容的提问来源于stack exchange,提问作者Codin Mark

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 00:35:30