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

如何从位图创建带透明(Alpha通道)的系统托盘数字图标?

修复系统托盘图标透明显示问题

你当前的代码存在两个核心问题导致透明失效:

  • 32位DIB section的Alpha通道未初始化,默认像素Alpha值为255(完全不透明),导致文字外的区域显示为黑色背景
  • 手动创建了单色掩码位图hMaskBmp,系统会优先使用掩码而非Alpha通道处理透明,覆盖了Alpha效果

以下是修正后的代码:

function CreateHiColorIcon(DC: HDC; nWidth, nHeight: Integer; Status: Byte; Color: COLORREF): HICON;
var
  lpbi: PBITMAPINFO;
  lpBits: Pointer;
  hBmp, hOldBitmap: HBITMAP;
  hMemDC: HDC;
  OldFnt, Fnt: HFONT;
  Sts: string;
  R: TRect;
  IconInfo: TIconInfo;
  Icon: HICON;
  PixelData: PRGBQuad;
  I: Integer;
  PixelCount: Integer;
begin
  Result := 0;

  // 分配BITMAPINFO结构,32位无需调色板,仅需BITMAPINFOHEADER
  GetMem(lpbi, SizeOf(TBITMAPINFOHEADER));
  try
    with lpbi^.bmiHeader do
    begin
      biSize := SizeOf(TBITMAPINFOHEADER);
      biWidth := nWidth;
      biHeight := nHeight;
      biPlanes := 1;
      biBitCount := 32; // 带Alpha通道的32位DIB
      biCompression := BI_RGB;
      biSizeImage := 0;
      biXPelsPerMeter := 0;
      biYPelsPerMeter := 0;
      biClrUsed := 0;
      biClrImportant := 0;
    end;

    hBmp := CreateDIBSection(DC, lpbi^, DIB_RGB_COLORS, lpBits, 0, 0);
    if hBmp = 0 then
      RaiseLastOSError;

    try
      // 初始化所有像素的Alpha通道为0(全透明)
      PixelCount := nWidth * nHeight;
      PixelData := lpBits;
      for I := 0 to PixelCount - 1 do
      begin
        PixelData^.rgbReserved := 0; // Alpha分量设为0
        Inc(PixelData);
      end;

      hMemDC := CreateCompatibleDC(DC);
      if hMemDC = 0 then
        RaiseLastOSError;

      try
        hOldBitmap := SelectObject(hMemDC, hBmp);
        if hOldBitmap = 0 then
          RaiseLastOSError;

        try
          Sts := IntToStr(Status);
          Fnt := GetNCMFont; // 获取窗口标题字体

          OldFnt := SelectObject(hMemDC, Fnt);
          R := TRect.Create(0, 0, nWidth, nHeight);
          SetBkMode(hMemDC, TRANSPARENT);
          SetTextColor(hMemDC, Color);
          // 绘制文字,文字区域的Alpha会被自动设为255(不透明)
          DrawTextEx(hMemDC, PWideChar(Sts), -1, R,
            DT_CENTER or DT_VCENTER or DT_SINGLELINE or DT_NOCLIP, nil);

          // 配置图标信息:依赖32位位图的Alpha通道实现透明
          ZeroMemory(@IconInfo, SizeOf(TIconInfo));
          IconInfo.fIcon := TRUE;
          IconInfo.hbmColor := hBmp;
          IconInfo.hbmMask := 0; // 无需手动设置掩码,系统自动从Alpha通道生成

          Icon := CreateIconIndirect(IconInfo);
          if Icon = 0 then
            RaiseLastOSError;

          Result := Icon;
        finally
          SelectObject(hMemDC, hOldBitmap);
          SelectObject(hMemDC, OldFnt);
          DeleteObject(Fnt);
        end;
      finally
        DeleteDC(hMemDC);
      end;
    finally
      DeleteObject(hBmp);
    end;
  finally
    FreeMem(lpbi);
  end;
end;

关键修改说明

  • 初始化Alpha通道:创建DIB后遍历所有像素,将Alpha分量(rgbReserved)设为0,确保文字以外的区域完全透明
  • 移除手动掩码:不再创建单色掩码位图,将IconInfo.hbmMask设为0,让系统优先使用32位位图的Alpha通道处理透明逻辑
  • 简化内存分配:32位DIB不需要调色板,仅分配BITMAPINFOHEADER的内存即可,减少不必要的内存开销

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 14:59:58