Search code examples
delphitransparencydelphi-7alphablending

How to draw a translucent image on a form?


I want to a draw a translucent image on a Delphi form, but for some reason it is not working.

Here is the original PNG (border is semi transparent):
Transparent border

I load the image in a TTntImage object:

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

TImage

The application:
Application


The image isn't translucent. I am working with a BMP image that contains the alpha channel. Am I missing something?


Solution

  • I found a solution that will let you draw a BMP image with an alpha channel onto a form using only the Windows API:

    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;
    

    Using The GIMP, I converted the PNG image

    found here to a 32-bit RGBA bitmap, found here, and the result is very good: