Delphi PNG Alpha Mix Attenuation

I asked a question about this several years ago when Vista was first released, but it never resolved the problem and put it off as something that could be considered later.

I have a screen saver in which I made great efforts to look great. This is a 32 bit alpha mixed PNG. I have a code (which I can dig out if necessary!), Which works fine under Windows XP or under Vista + when the desktop composition is disabled. However, in Vista +, all transparent parts are black, destroying everything that looks great!

So my question is this: since anyone could display a 32-bit alpha-mixed PNG as a screensaver in a way that works with and without the desktop ? I am not opposed to using third-party components, if necessary, for free or in another way.

Ideally, this will work in Delphi 7.

Update. Besides the answers below, which work very well, I found that the TMS component TAdvSmoothSplashScreen also does this task very well, if somewhat more complicated.

+4
source share
2 answers

Tim, I just tried this on Vista / D2007 with the Windows Classic theme selected:

Alpha Blended Splash Screen in Delphi - Part 2 http://melander.dk/articles/alphasplash2/2/

there is no black background that I could see ... it still looks great.

+6
source

Link to Bob S article gives the correct answer. Since this article contains quite a bit of additional information that you really need, here is the form / unit that I create through it (note that you will need the GraphicEx library from here :

unit Splash2Form; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, GraphicEx; type TSplash2 = class(TForm) private { Private declarations } procedure PreMultiplyBitmap(Bitmap: TBitmap); public constructor Create(Owner: TComponent);override; { Public declarations } procedure CreateParams(var Params: TCreateParams);override; procedure Execute; end; var Splash2: TSplash2; implementation {$R *.dfm} { TSplash2 } constructor TSplash2.Create(Owner: TComponent); begin inherited; Brush.Style := bsClear; end; procedure TSplash2.CreateParams(var Params: TCreateParams); begin inherited; end; procedure TSplash2.Execute; var exStyle: DWORD; BitmapPos: TPoint; BitmapSize: TSize; BlendFunction: TBlendFunction; PNG: TPNGGraphic; Stream: TResourceStream; begin // Enable window layering exStyle := GetWindowLongA(Handle, GWL_EXSTYLE); if (exStyle and WS_EX_LAYERED = 0) then SetWindowLong(Handle, GWL_EXSTYLE, exStyle or WS_EX_LAYERED); PNG := TPNGGraphic.Create; try Stream := TResourceStream.Create(HInstance, 'SPLASH', RT_RCDATA); try PNG.LoadFromStream(Stream); finally Stream.Free; end; PreMultiplyBitmap(PNG); ClientWidth := PNG.Width; ClientHeight := PNG.Height; BitmapPos := Point(0, 0); BitmapSize.cx := ClientWidth; BitmapSize.cy := ClientHeight; // Setup alpha blending parameters BlendFunction.BlendOp := AC_SRC_OVER; BlendFunction.BlendFlags := 0; BlendFunction.SourceConstantAlpha := 255; BlendFunction.AlphaFormat := AC_SRC_ALPHA; // ... and action! UpdateLayeredWindow(Handle, 0, nil, @BitmapSize, PNG.Canvas.Handle, @BitmapPos, 0, @BlendFunction, ULW_ALPHA); Show; finally PNG.Free; end; end; procedure TSplash2.PreMultiplyBitmap(Bitmap: TBitmap); var Row, Col: integer; p: PRGBQuad; PreMult: array[byte, byte] of byte; begin // precalculate all possible values of a*b for Row := 0 to 255 do for Col := Row to 255 do begin PreMult[Row, Col] := Row*Col div 255; if (Row <> Col) then PreMult[Col, Row] := PreMult[Row, Col]; // a*b = b*a end; for Row := 0 to Bitmap.Height-1 do begin Col := Bitmap.Width; p := Bitmap.ScanLine[Row]; while (Col > 0) do begin p.rgbBlue := PreMult[p.rgbReserved, p.rgbBlue]; p.rgbGreen := PreMult[p.rgbReserved, p.rgbGreen]; p.rgbRed := PreMult[p.rgbReserved, p.rgbRed]; inc(p); dec(Col); end; end; end; end. 
+6
source

All Articles