AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

NonVCL: SplashScreen

Ein Thema von wicht · begonnen am 12. Jun 2012 · letzter Beitrag vom 12. Jun 2012
Antwort Antwort
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#1

NonVCL: SplashScreen

  Alt 12. Jun 2012, 09:50
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
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#2

AW: NonVCL: SplashScreen

  Alt 12. Jun 2012, 10:08
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.
$2B or not $2B

Geändert von himitsu (12. Jun 2012 um 10:10 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#3

AW: NonVCL: SplashScreen

  Alt 12. Jun 2012, 10:44
Code:
C:\Dokumente und Einstellungen\mp>net helpmsg 317
317 ist keine gültige Windows-Netzwerknachrichtsnummer.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#4

AW: NonVCL: SplashScreen

  Alt 12. Jun 2012, 11:25
Delphi-Referenz durchsuchenSysErrorMessage oder Delphi-Referenz durchsuchenRaiseLastOSError (Delphi-Referenz durchsuchenRaiseLastWin32Error)

Zitat:
ERROR_MR_MID_NOT_FOUND

317 (0x13D)

The system cannot find message text for message number 0x%1 in the message file for %2.
$2B or not $2B

Geändert von himitsu (12. Jun 2012 um 11:27 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#5

AW: NonVCL: SplashScreen

  Alt 12. Jun 2012, 12:42
ja, das wollte ich jetzt nicht noch mal extra programmieren. Ich dachte net helpmsg würde auch helfen.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#6

AW: NonVCL: SplashScreen

  Alt 12. Jun 2012, 12:43
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...
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#7

AW: NonVCL: SplashScreen

  Alt 12. Jun 2012, 13:01
Eventuell ja nur ein Threaddingfehler oder ein Folgefehler?
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#8

AW: NonVCL: SplashScreen

  Alt 12. Jun 2012, 13:11
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)));
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#9

AW: NonVCL: SplashScreen

  Alt 12. Jun 2012, 14:17
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
$2B or not $2B
  Mit Zitat antworten Zitat
Benutzerbild von wicht
wicht

Registriert seit: 15. Jan 2006
Ort: Das schöne Enger nahe Bielefeld
809 Beiträge
 
Delphi XE Professional
 
#10

AW: NonVCL: SplashScreen

  Alt 12. Jun 2012, 15:08
Ja, da hast du wohl recht.. nur dem auf die Schliche zu kommen macht das natürlich nicht einfacher...
http://streamwriter.org

"I make hits. Not the public. I tell the DJ’s what to play. Understand?"
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:52 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz