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

使用GetDIBits捕获屏幕/窗口区域时无输出的问题排查

问题修复方案

核心问题排查与修复

1. 修正BitmapInfo的size字段赋值

BITMAPINFOHEADER的biSize固定为40(对应原生结构的字节大小),请确保该字段赋值正确,替换代码中的biSize变量为固定值:

info.header.size = 40;

2. 为GetDIBits的DllImport添加输出标记

.NET默认不会将数组自动识别为输出参数,需在DllImport中显式添加[Out]属性,确保数据能正确写入数组:

[DllImport("gdi32")]
public static extern int GetDIBits(IntPtr context, IntPtr bitmap, uint start, uint lines, [Out] RGBQuad[] bits, ref BitmapInfo header, uint usage);

3. 校验RGBQuad结构定义

确保你的RGBQuad与Win32原生结构完全匹配,正确定义如下:

[StructLayout(LayoutKind.Sequential)]
public struct RGBQuad
{
    public byte rgbBlue;
    public byte rgbGreen;
    public byte rgbRed;
    public byte rgbReserved;
}

4. 规范GDI资源管理

调用SelectObject后保存旧对象并最终恢复,避免资源泄漏和上下文异常:

var oldBitmap = SelectObject(newDC, map);
// 中间业务代码
SelectObject(newDC, oldBitmap); // 恢复原DC对象
DeleteObject(map);
DeleteDC(newDC);

5. 添加错误检查

通过GetDIBits的返回值和GetLastError排查执行失败原因:

int result = GetDIBits(newDC, map, 0, height, pixels, ref info, 0);
if (result == 0)
{
    int errorCode = Marshal.GetLastWin32Error();
    throw new System.ComponentModel.Win32Exception(errorCode);
}

完整修复后的核心代码

public RGBQuad[] GetBitmap(int x, int y, uint width, uint height)
{
    var newDC = CreateCompatibleDC(context);
    var map = CreateCompatibleBitmap(context, width, height);
    var oldBitmap = SelectObject(newDC, map);

    var info = new BitmapInfo();
    info.header.bitCount = 32;
    info.header.compression = 0; // BI_RGB
    info.header.planes = 1;
    info.header.width = (int)width; // 匹配原生结构的int类型
    info.header.height = -(int)height; // 负数表示正向像素顺序,避免翻转
    info.header.size = 40; // 固定为BITMAPINFOHEADER的字节大小
    info.header.sizeImage = width * height * 4; // 显式指定32位图像的总字节数

    var pixels = new RGBQuad[width * height];
    BitBlt(newDC, 0, 0, width, height, context, x, y, 13369376 /*SRCCOPY*/);
    
    int result = GetDIBits(newDC, map, 0, height, pixels, ref info, 0 /*DIB_RGB_COLORS*/);
    if (result == 0)
    {
        throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
    }

    SelectObject(newDC, oldBitmap);
    DeleteObject(map);
    DeleteDC(newDC);
    return pixels;
}

额外说明

  • 将height设为负数,可让GetDIBits返回从上到下的正向像素顺序,无需后续翻转数组。
  • 显式设置sizeImage能帮助GDI精准计算缓冲区大小,降低读取失败概率。

内容的提问来源于stack exchange,提问作者Aidan Reid

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:57:41