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

Delphi 12.1 FireMonkey捕获屏幕出现黑块问题求助

解决FireMonkey桌面截图出现黑色矩形的问题

问题根源

FireMonkey的TBitmap与VCL的TBitmap底层实现完全不同,它的Handle属性并非直接对应GDI的HBITMAP,直接调用BitBlt写入会导致无法正确捕获图像,最终生成黑色矩形。

解决方案(无需额外外部库)

方法1:使用FMX原生屏幕捕获(推荐)

FireMonkey自带屏幕捕获API,代码简洁且避免格式兼容问题:

var
  ScreenShot: TBitmap;
begin
  ScreenShot := TBitmap.Create(Round(aRect.Width), Round(aRect.Height));
  try
    // 捕获指定区域的屏幕内容
    ScreenShot.CaptureFromScreen(aRect);
    ScreenShot.SaveToFile('test.bmp');
  finally
    ScreenShot.Free;
  end;
end;

方法2:GDI位图中转(底层控制场景)

如果需要更底层的GDI操作,可通过GDI位图捕获后转换为FMX格式:

const
  CAPTUREBLT = $40000000;
var
  GdiBitmap: HBITMAP;
  GdiMemDC: HDC;
  ScreenDC: HDC;
  FmxBitmap: TBitmap;
  BitmapInfo: TBitmapInfo;
  BitmapData: Pointer;
begin
  ScreenDC := GetDC(0);
  try
    // 初始化GDI位图信息
    ZeroMemory(@BitmapInfo, SizeOf(BitmapInfo));
    BitmapInfo.bmiHeader.biSize := SizeOf(BitmapInfo.bmiHeader);
    BitmapInfo.bmiHeader.biWidth := 300;
    BitmapInfo.bmiHeader.biHeight := -300; // 负高度表示从上到下的图像
    BitmapInfo.bmiHeader.biPlanes := 1;
    BitmapInfo.bmiHeader.biBitCount := 32;
    BitmapInfo.bmiHeader.biCompression := BI_RGB;

    GdiMemDC := CreateCompatibleDC(ScreenDC);
    try
      GdiBitmap := CreateDIBSection(ScreenDC, BitmapInfo, DIB_RGB_COLORS, BitmapData, 0, 0);
      if GdiBitmap <> 0 then
      try
        SelectObject(GdiMemDC, GdiBitmap);
        // 捕获屏幕到GDI位图
        BitBlt(GdiMemDC, 0, 0, 300, 300, ScreenDC, Round(aRect.Left), Round(aRect.Top), SRCCOPY or CAPTUREBLT);
        
        // 转换为FMX TBitmap(处理BGRA转RGBA格式差异)
        FmxBitmap := TBitmap.Create(300, 300);
        try
          FmxBitmap.Map(TMapAccess.Write);
          try
            var SrcPtr := PByte(BitmapData);
            var DestPtr := PByte(FmxBitmap.Scanline[0]);
            for y := 0 to FmxBitmap.Height - 1 do
            begin
              var RowSrc := SrcPtr;
              var RowDest := DestPtr;
              for x := 0 to FmxBitmap.Width - 1 do
              begin
                RowDest^ := RowSrc[2]; // R通道
                Inc(RowDest);
                RowDest^ := RowSrc[1]; // G通道
                Inc(RowDest);
                RowDest^ := RowSrc[0]; // B通道
                Inc(RowDest);
                RowDest^ := RowSrc[3]; // A通道
                Inc(RowDest);
                Inc(RowSrc, 4);
              end;
              Inc(SrcPtr, 300 * 4);
              Inc(DestPtr, FmxBitmap.RowBytes);
            end;
          finally
            FmxBitmap.Unmap;
          end;
          FmxBitmap.SaveToFile('test.bmp');
        finally
          FmxBitmap.Free;
        end;
      finally
        DeleteObject(GdiBitmap);
      end;
    finally
      DeleteDC(GdiMemDC);
    end;
  finally
    ReleaseDC(0, ScreenDC);
  end;
end;

关键说明

  • 方法1是FMX原生实现,无需处理像素格式转换,代码更简洁,优先选用。
  • 方法2需注意GDI的32位位图为BGRA格式,而FMX的TBitmap为RGBA格式,必须转换通道顺序才能显示正确图像。

内容的提问来源于stack exchange,提问作者Peter Jones

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 08:42:05