如何在不创建临时DIB区域的情况下,从32bpp TBitmap实例中创建α混合的图标/光标(间接)?

5
根据微软支持页面MS KB entry的说明,CreateIconIndirect存在一个怪癖,它只能识别使用BITMAPV5HEADER(以及BGRA通道布局)作为参数创建的HBITMAP

然而,当引用其Handle时,(PixelFormat = pf32bit) and (AlphaFormat = afDefined)(在其他情况下作为 alpha 混合处理)的 TBitmap 实例并不被识别为有效的 alpha 混合位图,不能用于创建图标或光标。
当前,我必须使用所述的 API 调用 (请参见) 创建 TBitmap 的完整副本,以使 CreateIconIndirect 接受 alpha 混合的位图句柄。如何克服这种笨拙?

你检查过 Delphi 位图对象是否使用了正确的头文件类型吗?可以通过调用 Graphics.GetDIB 进行检查。 - David Heffernan
1个回答

8

这里有一个例子:

procedure TForm1.Button1Click(Sender: TObject);
const
  crAlpha = TCursor(-25);
var
  Bmp: TBitmap;
  Px: PRGBQuad;
  X, Y: Integer;

  BmpMask: TBitmap;
  II: TIconInfo;
  AlphaCursor: HCURSOR;
begin
  Bmp := TBitmap.Create;
  Bmp.PixelFormat := pf32bit;
  Bmp.Canvas.Brush.Color := clWhite;
  Bmp.SetSize(32, 32);
  Bmp.Canvas.Font.Style := [fsBold];
  Bmp.Canvas.Font.Color := clRed;
  Bmp.Canvas.TextOut(1, 10, 'alpha');

  for Y := 0 to (Bmp.Height - 1) do
  begin
    Px := Bmp.ScanLine[Y];
    for X := 0 to (Bmp.Width - 1) do begin
      if DWORD(Px^) = DWORD(clWhite) then
        Px.rgbReserved := $00
      else
        Px.rgbReserved := $FF;
      Inc(Px);
    end;
  end;

  BmpMask := TBitmap.Create;
  BmpMask.SetSize(Bmp.Width, Bmp.Height);

  II.fIcon := False;
  II.xHotspot := 32;
  II.yHotspot := 32;
  II.hbmMask := BmpMask.Handle;
  II.hbmColor := Bmp.Handle;

  AlphaCursor := CreateIconIndirect(II);
  Win32Check(AlphaCursor <> 0);
  BmpMask.Free;
  Bmp.AlphaFormat := afDefined;  // AlphaBlend below, premultiply channels
  Canvas.Draw(0, 0, Bmp);        // test draw
  Bmp.Free;

  Screen.Cursors[crAlpha] := AlphaCursor;
  Cursor := crAlpha;

end;


示例图片(顶部的“alpha”是测试绘图,另一个是光标)


@user - AlphaFormat是一个VCL枚举(它只告诉VCL是否应该应用预乘法),它不是存储在文件中的东西 - 当然,这个断言应该失败。但是保持AlphaFormat不变,根据示例代码,AFAICS您的dib将成为一个保留其透明度的光标。 - Sertac Akyuz
这是它:http://www.everfall.com/paste/id.php?f2c6atbrjrk6 看起来实际示例与合成示例有些特殊... - OnTheFly
1
我认为在从文件加载位图时,您需要完全删除Bmp.AlphaFormat := afDefined;这一行(也在我的第一条评论中提到)。无论如何,我几乎不会称之为“未被识别为有效的Alpha混合位图”。 - Sertac Akyuz
1
或者在设置AlphaFormat之前将PixelFormat设置为pfDevice(这将把位图复制到DDB)。 - Sertac Akyuz
1
嗯,将 AlphaFormat 设置为 afIgnored 可以消除两个结果图标和光标中的锐利效果。也就是说,要绘制 alpha 混合位图需要使用 afDefined,但 CreateIconIndirect 却需要 afIgnored(??)。这对我来说似乎有点违反直觉。你知道这可能是为什么吗? - OnTheFly
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接