从位图创建具有透明度(Alpha 通道)的图标

问题描述 投票:0回答:1

我正在寻找一种方法来为系统托盘应用程序创建一个图标,该图标使用出现在其上的数字来显示信息。

创建 DC 并在其上绘制数字不是问题(即使使用 Alpha 通道),但我无法以任何方式将其正确传输到图标。

这是我最近尝试过的东西,这似乎接近我需要的,但是当我尝试在窗口中绘制它(使用 DrawIconEx)时,它在数字周围显示一个黑色方块,而不是窗口背景。

有人可以指导我更正此代码,以便正确传输透明度吗?

谢谢!

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

  GetMem(lpbi, SizeOf(TBITMAPINFOHEADER) + SizeOf(TRGBQuad) * 256);

  try
    with lpbi^.bmiHeader do
    begin
      biSize := SizeOf(TBITMAPINFOHEADER);
      biWidth := nWidth;
      biHeight := nHeight;
      biPlanes := 1;
      biBitCount := 32; // Use a 32-bit DIB section with an alpha channel.
      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
      hMemDC := CreateCompatibleDC(DC);
      if hMemDC = 0 then
        RaiseLastOSError;

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

        try
          Sts := IntToStr(Status);
          Fnt := GetNCMFont; // Uses SystemParametersInfo to get the font used for the window titles (which I use for drawing)

          OldFnt := SelectObject(hMemDC, Fnt);
          R := TRect.Create(0, 0, nWidth, nHeight);
          SetBkMode(hMemDC, TRANSPARENT);
          SetTextColor(hMemDC, Color);
          DrawTextEx(hMemDC, PWideChar(Sts), -1, R,
            DT_CENTER or DT_VCENTER or DT_SINGLELINE or DT_NOCLIP, nil);

          hMaskBmp := CreateBitmap(nWidth, nHeight, 1, 1, nil);

          IconInfo.fIcon := TRUE;
          IconInfo.xHotspot := 0;
          IconInfo.yHotspot := 0;
          IconInfo.hbmMask := hMaskBmp;
          IconInfo.hbmColor := hBmp;

          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);
      DeleteObject(hMaskBmp);
    end;
  finally
    FreeMem(lpbi);
  end;
end;
winapi delphi-11-alexandria
1个回答
0
投票

要制作透明图标,您需要使用

hbmMask
来“屏蔽”您想要透明的像素。但你并没有这样做。您正在为蒙版创建一个空的 1x1 位图。对于颜色图标,
hbmColor
hbmMask
需要具有相同的尺寸。
hbmMask
将用于异或
hbmColor

中的像素
© www.soinside.com 2019 - 2024. All rights reserved.