|
| 1 | +unit Splash; |
| 2 | + |
| 3 | +interface |
| 4 | + |
| 5 | +uses |
| 6 | + Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, |
| 7 | + Dialogs, ExtCtrls, GDIPAPI, GDIpOBJ, Activex; |
| 8 | + |
| 9 | +type |
| 10 | + TFormSplash = class(TForm) |
| 11 | + TimerSplash: TTimer; |
| 12 | + procedure FormClose(Sender: TObject; var Action: TCloseAction); |
| 13 | + procedure TimerSplashTimer(Sender: TObject); |
| 14 | + procedure FormKeyPress(Sender: TObject; var Key: Char); |
| 15 | + procedure FormClick(Sender: TObject); |
| 16 | + |
| 17 | + private |
| 18 | + { Private declarations } |
| 19 | + protected |
| 20 | + procedure WMNCHitTest(var message: TWMNCHitTest); message WM_NCHITTEST; |
| 21 | + public |
| 22 | + { Public declarations } |
| 23 | + procedure Execute; |
| 24 | + end; |
| 25 | + |
| 26 | +var |
| 27 | + FormSplash: TFormSplash; |
| 28 | + |
| 29 | +implementation |
| 30 | + |
| 31 | +{$R *.dfm} |
| 32 | + |
| 33 | +procedure TFormSplash.FormClose(Sender: TObject; var Action: TCloseAction); |
| 34 | +begin |
| 35 | + TimerSplash.Destroy; |
| 36 | + Action := caFree; |
| 37 | +end; |
| 38 | + |
| 39 | +procedure TFormSplash.TimerSplashTimer(Sender: TObject); |
| 40 | +begin |
| 41 | + Close; |
| 42 | +end; |
| 43 | + |
| 44 | +procedure TFormSplash.FormKeyPress(Sender: TObject; var Key: Char); |
| 45 | +begin |
| 46 | + Close; |
| 47 | +end; |
| 48 | + |
| 49 | +procedure TFormSplash.WMNCHitTest(var message: TWMNCHitTest); |
| 50 | +begin |
| 51 | + Message.Result := HTCAPTION; |
| 52 | +end; |
| 53 | + |
| 54 | +procedure PremultiplyBitmap(Bitmap: TBitmap); |
| 55 | +var |
| 56 | + Row, Col: integer; |
| 57 | + p: PRGBQuad; |
| 58 | + PreMult: array [byte, byte] of byte; |
| 59 | +begin |
| 60 | + // precalculate all possible values of a*b |
| 61 | + for Row := 0 to 255 do |
| 62 | + for Col := Row to 255 do |
| 63 | + begin |
| 64 | + PreMult[Row, Col] := Row * Col div 255; |
| 65 | + if (Row <> Col) then |
| 66 | + PreMult[Col, Row] := PreMult[Row, Col]; // a*b = b*a |
| 67 | + end; |
| 68 | + |
| 69 | + for Row := 0 to Bitmap.Height - 1 do |
| 70 | + begin |
| 71 | + Col := Bitmap.Width; |
| 72 | + p := Bitmap.ScanLine[Row]; |
| 73 | + while (Col > 0) do |
| 74 | + begin |
| 75 | + p.rgbBlue := PreMult[p.rgbReserved, p.rgbBlue]; |
| 76 | + p.rgbGreen := PreMult[p.rgbReserved, p.rgbGreen]; |
| 77 | + p.rgbRed := PreMult[p.rgbReserved, p.rgbRed]; |
| 78 | + inc(p); |
| 79 | + dec(Col); |
| 80 | + end; |
| 81 | + end; |
| 82 | +end; |
| 83 | + |
| 84 | +type |
| 85 | + TFixedStreamAdapter = class(TStreamAdapter) |
| 86 | + public |
| 87 | + function Stat(out statstg: TStatStg; grfStatFlag: DWORD): HResult; |
| 88 | + override; stdcall; |
| 89 | + end; |
| 90 | + |
| 91 | +function TFixedStreamAdapter.Stat(out statstg: TStatStg; |
| 92 | + grfStatFlag: DWORD): HResult; |
| 93 | +begin |
| 94 | + Result := inherited Stat(statstg, grfStatFlag); |
| 95 | + statstg.pwcsName := nil; |
| 96 | +end; |
| 97 | + |
| 98 | +procedure TFormSplash.Execute; |
| 99 | +var |
| 100 | + Ticks: DWORD; |
| 101 | + BlendFunction: TBlendFunction; |
| 102 | + BitmapPos: TPoint; |
| 103 | + BitmapSize: TSize; |
| 104 | + exStyle: DWORD; |
| 105 | + Bitmap: TBitmap; |
| 106 | + PNGBitmap: TGPBitmap; |
| 107 | + BitmapHandle: HBITMAP; |
| 108 | + Stream: TStream; |
| 109 | + StreamAdapter: IStream; |
| 110 | +begin |
| 111 | + // Enable window layering |
| 112 | + exStyle := GetWindowLongA(Handle, GWL_EXSTYLE); |
| 113 | + if (exStyle and WS_EX_LAYERED = 0) then |
| 114 | + SetWindowLong(Handle, GWL_EXSTYLE, exStyle or WS_EX_LAYERED); |
| 115 | + |
| 116 | + Bitmap := TBitmap.Create; |
| 117 | + try |
| 118 | + // Load the PNG from a resource |
| 119 | + Stream := TResourceStream.Create(HInstance, 'SPLASH', RT_RCDATA); |
| 120 | + try |
| 121 | + // Wrap the VCL stream in a COM IStream |
| 122 | + StreamAdapter := TFixedStreamAdapter.Create(Stream); |
| 123 | + try |
| 124 | + // Create and load a GDI+ bitmap from the stream |
| 125 | + PNGBitmap := TGPBitmap.Create(StreamAdapter); |
| 126 | + try |
| 127 | + // Convert the PNG to a 32 bit bitmap |
| 128 | + PNGBitmap.GetHBITMAP(MakeColor(0, 0, 0, 0), BitmapHandle); |
| 129 | + // Wrap the bitmap in a VCL TBitmap |
| 130 | + Bitmap.Handle := BitmapHandle; |
| 131 | + finally |
| 132 | + PNGBitmap.Free; |
| 133 | + end; |
| 134 | + finally |
| 135 | + StreamAdapter := nil; |
| 136 | + end; |
| 137 | + finally |
| 138 | + Stream.Free; |
| 139 | + end; |
| 140 | + |
| 141 | + ASSERT(Bitmap.PixelFormat = pf32bit, |
| 142 | + 'Wrong bitmap format - must be 32 bits/pixel'); |
| 143 | + |
| 144 | + // Perform run-time premultiplication |
| 145 | + PremultiplyBitmap(Bitmap); |
| 146 | + |
| 147 | + // Resize form to fit bitmap |
| 148 | + ClientWidth := Bitmap.Width; |
| 149 | + ClientHeight := Bitmap.Height; |
| 150 | + |
| 151 | + // Position bitmap on form |
| 152 | + BitmapPos := Point(0, 0); |
| 153 | + BitmapSize.cx := Bitmap.Width; |
| 154 | + BitmapSize.cy := Bitmap.Height; |
| 155 | + |
| 156 | + // Setup alpha blending parameters |
| 157 | + BlendFunction.BlendOp := AC_SRC_OVER; |
| 158 | + BlendFunction.BlendFlags := 0; |
| 159 | + BlendFunction.SourceConstantAlpha := 0; // Start completely transparent |
| 160 | + BlendFunction.AlphaFormat := AC_SRC_ALPHA; |
| 161 | + |
| 162 | + Show; |
| 163 | + // ... and action! |
| 164 | + Ticks := 0; |
| 165 | + while (BlendFunction.SourceConstantAlpha < 255) do |
| 166 | + begin |
| 167 | + while (Ticks = GetTickCount) do |
| 168 | + Sleep(10); // Don't fade too fast |
| 169 | + Ticks := GetTickCount; |
| 170 | + inc(BlendFunction.SourceConstantAlpha, |
| 171 | + (255 - BlendFunction.SourceConstantAlpha) div 32 + 1); // Fade in |
| 172 | + UpdateLayeredWindow(Handle, 0, nil, @BitmapSize, Bitmap.Canvas.Handle, |
| 173 | + @BitmapPos, 0, @BlendFunction, ULW_ALPHA); |
| 174 | + end; |
| 175 | + finally |
| 176 | + Bitmap.Free; |
| 177 | + end; |
| 178 | + // Start timer to hide form after a short while |
| 179 | + TimerSplash.Enabled := True; |
| 180 | +end; |
| 181 | + |
| 182 | +procedure TFormSplash.FormClick(Sender: TObject); |
| 183 | +begin |
| 184 | + Close; |
| 185 | +end; |
| 186 | + |
| 187 | +end. |
0 commit comments