【问题标题】:How to draw a translucent image on a form?如何在表单上绘制半透明图像?
【发布时间】:2011-05-11 13:02:52
【问题描述】:

我想在 Delphi 表单上绘制半透明图像,但由于某种原因无法正常工作。

这是原始的PNG(边框是半透明的):

我将图像加载到 TImage 对象中:

Image1.Transparent := True;
Form1.Color := clWhite;
Form1.TransparentColor := True;
Form1.TransparentColorValue := clWhite;

申请:


图像不是半透明的。我正在使用包含 alpha 通道的 BMP 图像。我错过了什么吗?

【问题讨论】:

  • 我不明白如何在 Delphi 7 TImage 控件中使用 PNG 图像。 Delphi 7 不支持 PNG...
  • 嗯嗯嗯。它作为 PNGObject 加载。
  • D7 不支持 png。您已安装 3rd 方组件。你为什么反对 3rd 方组件?
  • 好的,使用第三方组件!哦哦。抱歉,我使用的是 TNT Unicode 控件。 TTntImage。
  • @Robrok:你的英文没问题,但是当你说你使用TImage但实际上使用的是TntImage时,这有点令人困惑!

标签: delphi transparency delphi-7 alphablending


【解决方案1】:

我找到了一个解决方案,可以让您仅使用 Windows API 将带有 alpha 通道的 BMP 图像绘制到表单上:

const
  AC_SRC_OVER = 0;
  AC_SRC_ALPHA = 1;

type
  BLENDFUNCTION = packed record
    BlendOp,
    BlendFlags,
    SourceConstantAlpha,
    AlphaFormat: byte;
  end;

function WinAlphaBlend(hdcDest: HDC; xoriginDest, yoriginDest, wDest, hDest: integer;
  hdcSrc: HDC; xoriginSrc, yoriginSrc, wSrc, hSrc: integer; ftn: BLENDFUNCTION): LongBool;
  stdcall; external 'Msimg32.dll' name 'AlphaBlend';

procedure TForm4.FormClick(Sender: TObject);
var
  hbm: HBITMAP;
  bm: BITMAP;
  bf: BLENDFUNCTION;
  dc: HDC;
begin
  hbm := LoadImage(0,
    'C:\Users\Andreas Rejbrand\Skrivbord\RatingCtrl.bmp',
    IMAGE_BITMAP,
    0,
    0,
    LR_LOADFROMFILE);
  if hbm = 0 then
    RaiseLastOSError;
  try
    if GetObject(hbm, sizeof(bm), @bm) = 0 then RaiseLastOSError;
    dc := CreateCompatibleDC(0);
    if dc = 0 then RaiseLastOSError;
    try
      if SelectObject(dc, hbm) = 0 then RaiseLastOSError;
      bf.BlendOp := AC_SRC_OVER;
      bf.BlendFlags := 0;
      bf.SourceConstantAlpha := 255;
      bf.AlphaFormat := AC_SRC_ALPHA;
      if not WinAlphaBlend(Canvas.Handle,
        10,
        10,
        bm.bmWidth,
        bm.bmHeight,
        dc,
        0,
        0,
        bm.bmWidth,
        bm.bmHeight,
        bf) then RaiseLastOSError;
    finally
      DeleteDC(dc);
    end;
  finally
    DeleteObject(hbm);
  end;
end;

使用 GIMP,我转换了 PNG 图像

找到here转为32位RGBA位图,找到here,结果很好:

【讨论】:

  • 是的,它有效。但是如果我想在表格周围画一个边框呢?
  • 我想创建可换肤的表单。
  • 不错!顺便说一句,您的代码适用于常规 gdi 函数声明,即windows.AlphaBlend(),无需声明常量、记录和函数..
  • @Sertac:我非常清楚这一点,但我不确定 AlphaBlend 是否在旧 Delphi 7(即 OP 的 Delphi 版本)附带的 Windows.pas 中声明。此外,在 Delphi 2009(我的 Delphi 版本)中 Windows.pas 中的 AlphaBlend 声明非常“丑陋”:function AlphaBlend(DC: HDC; p2, p3, p4, p5: Integer; DC6: HDC; p7, p8, p9, p10: Integer; p11: TBlendFunction): BOOL; stdcall; 但我想我应该为此写一个脚注。
  • 为什么我在 SO 上发表的每一篇帖子都被否决了?!?!
【解决方案2】:

为什么不尝试使用常规 bmp 将您的 png 绘制到新图像上。将您想要的内容绘制到图像 2 上,并在完成后重绘/或分配/全部到您的图像 1。必须有效...

【讨论】:

    【解决方案3】:

    TransparentColorValue 方法不可能奏效,因为这只适用于单一颜色表示完全透明的图像。 [另外,你是在玩弄 form 的 透明色而不是 image 的 透明色!] 上面的 PNG 图像应该有一个 alpha 通道,因此并不是每个像素都显示或透明 - 相反,每个像素的不透明度介于 0 和 1 之间(例如 0.37)。也就是说,除了每个像素的 R、G 和 B 分量之外,还有一个 'alpha' 分量 A。

    但是,上面的图像似乎已损坏。一个“正确”的 PNG 如下所示:


    (来源:rejbrand.se

    您可以尝试将上面的一个混合到不同的背景上,您会发现阴影融合得很好。

    那么,如果有一个“正确”的 PNG,如何将它绘制到表单上?好吧,在您的情况下这将非常困难,因为 Delphi 7 不支持 PNG 图像。它只支持 BMP 图像,并且这些图像通常没有 alpha 通道。

    【讨论】:

    • windows 位图通常有 alpha 通道
    • @David:是的,但我不确定 Delphi 7 TImage 是否可以处理这些问题。可以吗?
    • 经常大卫是什么意思?很少有工具支持带有 Alpha 通道的 .BMP 文件,那么您认为存储的 Windows .BMP 文件多久拥有一次呢?我会说接近 0.0001% 的人拥有它们。除了可能在您的计算机上。
    • @andreas 不,我非常怀疑。 Delphi 的 TBitmap 对 alpha 的支持非常迟缓。
    • @warren 谁说过文件?您认为 32bpp xp 图标在您的计算机中是如何表示的?
    猜你喜欢
    • 1970-01-01
    • 2011-11-18
    • 2017-09-22
    • 2010-12-01
    • 2021-03-22
    • 1970-01-01
    • 2011-01-27
    • 2014-03-13
    • 2020-10-24
    相关资源
    最近更新 更多