![]() |
NonVCL: SplashScreen
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:
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.
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; 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 :) |
AW: NonVCL: SplashScreen
Wenn du den SplashScreen im Thread erstellst (nicht im Hauptthread) und im Threrad natürlich eine MessageLoop (Nachtichtenverarbeitung) enthalten ist, dann läuft das Fenster vollkommen unabhängig von der VCL und es gibt auch keine Probleme mit dem Multithreading und vorallem nicht mit eventuellen langen Pausen im Huptthread.
Mit dem Thread wo das CrerateWindow aufgerufen wurde, wird die Messagebehandlung des Controls verbunden und alles was über die MessageQueue läuft, läuft dann in der MessageQueue dieses Threads und auch die ganzen internen Prozesse deiser Komponente laufen dann in diesem Thread. VCL-Komponenten müssen nur im Hauptthread laufen, da sie intern gemeinsame und nicht threadsichere Resourcen der VCL verwenden, wie z.B. irgendwelche Listen wo sie sich registrieren oder gemeinsam genutzte Fonts usw. |
AW: NonVCL: SplashScreen
Code:
C:\Dokumente und Einstellungen\mp>net helpmsg 317
317 ist keine gültige Windows-Netzwerknachrichtsnummer. |
AW: NonVCL: SplashScreen
![]() ![]() ![]() Zitat:
|
AW: NonVCL: SplashScreen
ja, das wollte ich jetzt nicht noch mal extra programmieren. Ich dachte net helpmsg würde auch helfen.
|
AW: NonVCL: SplashScreen
Danke für die Antworten!
"ERROR_MR_MID_NOT_FOUND" habe ich dazu auch gefunden - aber was soll mir das im Zusammenhang mit UpdateLayeredWindow() sagen? Das macht für mich überhaupt keinen Sinn... |
AW: NonVCL: SplashScreen
Eventuell ja nur ein Threaddingfehler oder ein Folgefehler?
|
AW: NonVCL: SplashScreen
Mein Code dazu sah so aus:
Delphi-Quellcode:
if not UpdateLayeredWindow(SplashWndHandle, 0, nil, @BitmapSize, SplashBitmap.Canvas.Handle, @SplashBitmapPos, 0, @BlendFunction, ULW_ALPHA) then
OutputDebugString(PChar(IntToStr(GetLastError))); |
AW: NonVCL: SplashScreen
Folgefehler: Innerhalb eines API-Aufrufs werden ja oftmals auch wieder weitere APIs/Funktionen aufgerufen ... der Folgefehler muß also nicht in deinem Code liegen.
Ansonsten macht sich direkt der Fehlertext einfach schöner.
Delphi-Quellcode:
OutputDebugString(PChar(SysErrorMessage(GetLastError)));
// bzw. E := GetLastError; OutputDebugString(PChar(IntToStr(E) + ': ' + SysErrorMessage(E))); // IntToStr und SysErrorMessage rufen auch WinAPIs auf |
AW: NonVCL: SplashScreen
Ja, da hast du wohl recht.. nur dem auf die Schliche zu kommen macht das natürlich nicht einfacher... :(
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:49 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz