Guten Morgen!
Am Wochenende war mir langweilig und ich dachte, ich baue mal einen Splash-Screen. Weil er "animiert" sein soll, während im Hintergrund das Main-Formular lädt, habe ich mich entschieden, einen TThread-Nachfahren zu bauen, der das Fenster erstellt und verwaltet. Ja, ich weiß, dass der Hauptthread im optimalen Falle den Splash erstellt und zum Laden der Daten ein Thread benutzt werden sollte, aber ein bisschen mit der
API spielen macht ja auch mal Spass. Ich erstelle also das Fenster und habe meine WindowProc, die poste ich mal:
Delphi-Quellcode:
function WindowProc(hwn, msg, wpr, lpr: Longint): Longint; stdcall;
var
H: HWND;
Val: Cardinal;
TC: Cardinal;
Msg2: TMsg;
P: TPoint;
begin
case msg of
WM_TIMER:
begin
TC := GetTickCount;
if AnimationStart = 0 then
AnimationStart := GetTickCount;
H := GetMainWindowWindow;
case State of
stFadeIn:
begin
Val := Trunc(((TC - AnimationStart) / FADE_TIME) * 254);
if TC - AnimationStart < FADE_TIME then
begin
BlendFunction.SourceConstantAlpha := Val;
UpdateLayeredWindow(SplashWndHandle, 0, nil, @BitmapSize, SplashBitmap.Canvas.Handle, @SplashBitmapPos, 0, @BlendFunction, ULW_ALPHA);
end else
begin
WaitingStarted := TC;
State := stWaiting;
end;
end;
stWaiting:
begin
if ((H > 0) and IsWindowVisible(H)) or ((TC - AnimationStart) > 2000) then
begin
State := stFadeOut;
AnimationStart := 0;
end;
end;
stFadeOut:
begin
Val := 254 - Trunc(((TC - AnimationStart) / FADE_TIME) * 254);
if TC - AnimationStart < FADE_TIME then
begin
BlendFunction.SourceConstantAlpha := Val;
// Das hier gibt manchmal Fehler 317 bei GetLastError() zurück?
UpdateLayeredWindow(SplashWndHandle, 0, nil, @BitmapSize, SplashBitmap.Canvas.Handle, @SplashBitmapPos, 0, @BlendFunction, ULW_ALPHA);
end else
begin
SplashBitmap.Free;
KillTimer(SplashWndHandle, 0);
Killed := True;
if H > 0 then
SetForegroundWindow(H);
end;
end;
end;
SetWindowPos(SplashWndHandle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE or SWP_NOACTIVATE);
end;
end;
Result := DefWindowProc(hwn, msg, wpr, lpr);
end;
Wie man sieht läuft das Fadein/Fadeout mit einem Timer. Das Problem habe ich mit einem Kommentar markiert. Der Fadein funktioniert gut, aber beim Fadeout gibt es manchmal den Fehler 317, was immer der hier bedeuten mag... Kann dazu vielleicht jemand etwas mehr sagen? Es sieht eben blöd aus, wenn der Screen schön einfadet aber beim Ausblenden bei 50% Transparenz "stehen bleibt" und dann direkt verschwindet, wenn das Hauptfenster da ist.
Eine andere Sache ist, ob man so etwas überhaupt mit einer WindowProc machen sollte. Ich habe in einem Beispiel gesehen, dass CreateWindowEx() aufgerufen wurde und dann direkt mit UpdateLayeredWindow() gearbeitet wurde. Ist das sinniger, wenn man nicht mehr als Fadein/Fadeout machen möchte? Und ist das ungefährlich?
Liebe Grüße und danke im Vorraus für eventuelle Antworten