[Gelöst] Splashscreenanzeige zu kurz

Für Fragen von Einsteigern und Programmieranfängern...
and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

[Gelöst] Splashscreenanzeige zu kurz

Beitrag von and4more »

Hallo liebes Forum, hab' schon wieder mal 'ne Frage. Nach Google-Internetsuche nach "Lazarus", "Splashscreen" u. a. verknüpfte Begriffe habe ich leider keine wirkliche Lösung für mein Problem gefunden:
Um meinem Programm einen etwas professionelleren Anstrich zu verleihen wollte ich gern einen Splashscreen einbauen. Also Form mit dem Designer erstellt, 'fsplash' eingestellt, komplett mit einem PNG-Image ausgefüllt, Überschrift weg und kompiliert.
...und toll, man kann den Splashscreen beim Start für etwa 5 Millisekunden erahnen und schon sieht man das Hauptprogramm, irgendwie nicht so wirklich befriedigend.
Versuche mit 'Sleep(1500)' sowohl bei Hauptform.Create, aber auch bei Splashform.Create führen zu keiner Verlängerung der Anzeigedauer des Splashscreens, auch die im Internet vorhandenen Empfehlungen mit Splashform.Update, Application.ProcessMessages in der .lpr-Datei oder im Hauptform.Create-Prozess führen nicht zu einer Veränderung. "Vorverlegung" von Application.CreateForm(TFrmSplash, Splashform) vor das Hauptformular führen dazu dass das Hauptprogramm gar nicht erst startet. Der Aufruf von Splashform.Show oder .Visible:=True im Create-Prozess in Kombination mit .Hide oder .Visible:=False des Hauptforms führen zu einer Exception. Leider ist auch sonst keine vernünftige Dokumentation zur 'fsplash' zu finden und auch im Designer gibt es keine Möglichkeit die Anzeigedauer einzustellen. Evtl. könnte man auch mit Threads arbeiten, um das Hauptprogramm im Hintergrund zu laden während der Splashscreeen angezeigt wird, doch finde ich das etwas überzogen.
Kennt jemand eine Dokumentation oder hat Erfahrung mit Splashscreens und vielleicht ein Beispiel, welches funktioniert?
Zuletzt geändert von and4more am Mi 30. Sep 2015, 23:22, insgesamt 1-mal geändert.
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Splashscreenanzeige zu kurz

Beitrag von Michl »

Ich kenne dieses Splashscreen nicht, habe aber eben einen kurzen Test gemacht und so könnte ich mir das vorstellen:

- ein eigenes Formular als Splashscreen entwerfen, einen Timer mit der gewünschten Anzeigedauer darauf
- im Event OnTimer das Formular schließen
- beim OnCreate des Formulars per Application.QueueAsyncall das Formular zu Ansicht bringen

Allerdings wird der Splashscreen erst angezeigt, wenn das Laden des Programms abgschlossen ist. Bei Programmen, die eine längere Initialiserung benötigen, würde ich diese Initialisierung per Thread erledigen (zumindest habe ich das so bei einem Programm mit Datenbankzugriff gemacht, welches eine recht lange Zeit zur vollen Verfügbarkeit benötigt).

Das kleine Testprog ist im Anhang.
Dateianhänge
Splashscreen.zip
(2.5 KiB) 96-mal heruntergeladen

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: Splashscreenanzeige zu kurz

Beitrag von TBug »

Im Anhang einmal ein Splash-Screen-Beispiel, bei dem der Splash-Screen von Anfang an angezeigt wird.

Schau dir speziell einmal die lpr-Datei an.
Dateianhänge
SplashScreen.zip
(126.24 KiB) 117-mal heruntergeladen

and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Re: Splashscreenanzeige zu kurz

Beitrag von and4more »

...mit einem 'normalen' Form (fsnormal) klappt das auch, da geht z. B. auch 'Sleep()', allerdings werden hierbei auch die Rahmen des Forms und der ganze Hintergrund mit angezeigt. In meinem Fall möchte ich aber nur ein Bild (Lazarus-Logo mit umlaufender Schrift) darstellen, also ohne Ränder oder irgendwas sonst. Dies ist mit 'fsSplash' möglich. Allerdings funktionieren hierbei auch viele Funktionen, die sonst für 'normale' Forms gehen nicht mehr. Warum bleibt unklar (Bug/Feature)?
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: Splashscreenanzeige zu kurz

Beitrag von TBug »

and4more hat geschrieben: In meinem Fall möchte ich aber nur ein Bild (Lazarus-Logo mit umlaufender Schrift) darstellen, also ohne Ränder oder irgendwas sonst.
In meinem Beispiel hat der Splash-Screen auch keinen Rahmen.

and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Re: Splashscreenanzeige zu kurz

Beitrag von and4more »

TBug hat geschrieben:In meinem Beispiel hat der Splash-Screen auch keinen Rahmen.
Korrekt, aber es ist ein viereckiges Fenster. Das Bild/Logo das ich habe ist rund und somit ist ein rundes Logo in einem eckigen Hintergrund. Sieht halt irgendwie "zusammengefrickelt" aus, was natürlich keine Abwertung oder Kritik Deines wirklich guten Tipps sein soll. Super wäre halt wenn irgendjemand wüsste, wie man das entweder mit 'fsSplash' steuern könnte oder die Hintergrundform so ausblenden könnte, dass wirklich nur das Bild zu sehen ist. Klappt leider auch nicht über 'AlphaBlend', da hierbei leider auch das Logo durchsichtig wird.
Dateianhänge
ScreenShot.png
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

Komoluna
Beiträge: 565
Registriert: So 26. Aug 2012, 09:03
OS, Lazarus, FPC: Windows(10), Linux(Arch)
CPU-Target: 64Bit

Re: Splashscreenanzeige zu kurz

Beitrag von Komoluna »

TheRegRunner hat dazu ein Video:

https://www.youtube.com/watch?v=TQrg5agc1ok
Sourcecode als GDrive link in der Beschreibung.

MFG

Komoluna
Programmer: A device to convert coffee into software.

Rekursion: siehe Rekursion.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Splashscreenanzeige zu kurz

Beitrag von Michl »

Kannst du nicht das Minimalbsp. hier hochladen, dann könnte man dies testen. Bei mir funktioniert es mit FormStyle fsSplash mit Sleep schon, wobei dann alle weiteren Ladevorgänge angehalten werden und dieses Formular auch rechteckig ist.

Auszug aus der lpr:

Code: Alles auswählen

begin
  RequireDerivedFormResource := True;
  Application.Initialize;
  Form2 := TForm2.Create(Nil);
  Form2.Show;
  Form2.Refresh;
  Application.ProcessMessages;
  Sleep(2000);
  Form2.Close;
  Form2.Release;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.   
[Edit] Evtl. ist Komolunas Link ja hilfreich oder dieser für Windows: http://melander.dk/articles/alphasplash

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Re: Splashscreenanzeige zu kurz

Beitrag von and4more »

@komoluna: Ja, hatte ich mir auch schon angeschaut und überlegt, wegen Faulheit aber erstmal verworfen, weil ich dachte dass 'fsSplash' nur das Bild ohne Hintergrundfenster anzeigt, aber jetzt wo's geklappt hat (Super vielen Dank an Michl. Weiß auch nicht was ich zuerst falsch gemacht hatte) sieht man doch (bei längerer Darstellung des Fensters) dass auch hierbei der Hintergrund rechteckig erscheint. Insofern werde ich wohl nicht drumrumkommen nun auch die Form anzupassen. Allerdings ist mir jetzt total unklar worin der Unterschied zwischen 'fsSplash' und 'fsnormal' besteht. Nochmals vielen Dank an Alle für die Mühe.
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

TBug
Beiträge: 179
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: Splashscreenanzeige zu kurz

Beitrag von TBug »

and4more hat geschrieben:Das Bild/Logo das ich habe ist rund und somit ist ein rundes Logo in einem eckigen Hintergrund. Sieht halt irgendwie "zusammengefrickelt" aus, ...
Ist halt Lazarus und nicht Delphi. In letzterem könntest Du mittels den TForm-Properties Color, TransparentColor und TransparentColorValue den Formular-Hintergrund komplett durchsichtig machen, ohne dass alle auf der Form liegende Elemente auch transparent werden. Dadurch ist es möglich, wie vom TE gewünscht nur ein rundes Bild anzuzeigen.


.

and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Re: [Gelöst] Splashscreenanzeige zu kurz

Beitrag von and4more »

ORCHK.PNG
So nachdem ich nun ein wenig herumprobiert habe möchte ich mich abschließend mit einem (sehr) kleinen Tutorial bedanken für alle,die die gleichen oder ähnliche Probleme habe (und da scheint es im Internet einige zu geben):

1. Im Designer (oder dynamisch) eine kleine Form in gewünschter Größe erstellen mit BorderStyle:=bsnone; und FormStyle:=fsSplash; Bei der Position kann man je nach Geschmack z. B. 'poDesktopCenter' für mittige Darstellung auf dem Desktop einstellen. Danach in das eben angefertigte Form ein TImage (aus dem Reiter 'Additional') zentral in das Form einfügen und über Anchors am besten mittig im Auswahlfeld 15 Punkte Abstand einstellen. Dies war bei mir erforderlich da sonst die Ränder des Bildes später bei ShapeControl abgeschnitten werden (warum auch immer?!?). Dann in 'Picture' das gewünschte Bild wählen, ggf. 'Stretch':=True einstellen

2. In der .lpr Datei sollte einmal die eben erstellte unit, nennen wir sie FrmSplash, aufgeführt sein und wenn die Darstellung des SplashScreens länger sein soll ggf. noch 'sysutils' für die Funktion 'Sleep()' hinzufügen. Nach Aplication.initialize; dann bitte folgendes eintragen:

Code: Alles auswählen

 
  FrmSplash:=TFrmSplash.Create(NIL);
  FrmSplash.Show;
  FrmSplash.Refresh;
  Application.ProcessMessages;     //wann ist das Hauptprogramm fertig
  Sleep(1500);           //SplashScreen wird 1,5 Sekunden angezeigt, aber: alles andere stoppt, also auch Ladevorgänge des Hauptprogramm, daher weglassen, wenn der Start des Hauptprogramms eh lang dauert
  FrmSplash.Close;
  FrmSplash.Release;
 
vor

Code: Alles auswählen

 
  Application.CreateForm(TFrmMain, FrmMain);
  //Application.CreateForm(TFrmSplash, FrmSplash);  //-> ist zu löschen oder auszukommentieren
 
3. In der unit der Splashform sollte oben stehen:

Code: Alles auswählen

 
  public
    { public declarations }
    procedure ShapeControl(AControl: TWinControl);
 

im Implementationsteil folgendes:

Code: Alles auswählen

 
procedure TFrmSplash.FormShow(Sender: TObject);
begin
  ShapeControl(Self);
end;
 
procedure TFrmSplash.ShapeControl(AControl: TWinControl);
var
  ABitmap: TBitmap;
begin
  BorderStyle:=bsNone; //wenn's bereits eingestellt ist, kann's auch hier gelöscht werden
  ABitmap:=TBitmap.Create;
  //ABitmap.PixelFormat:=pf1bit;   //Änderungsvorschlag von RegRunner
  ABitmap.Monochrome := True;        //soll laut RegRunner ein Fehler sein, konnte keinen entdecken
  //jetzt wird die Höhe und Breite der Bitmap bestimmt, die zum Maskieren der FrmSplash verwendet wird
  ABitmap.Width:=FrmSplash.Width;
  ABitmap.Height:=FrmSplash.Height;
 
  //Schwarzer Hintergrund (-> wird später transparent)
  ABitmap.Canvas.Brush.Color:=clBlack;
  ABitmap.Canvas.FillRect(0,0,Width,Height);    //Rechteck bzw. Quadrat
 
  //Die sichtbare Ebene muss weiss bleiben
  ABitmap.Canvas.Brush.Color:=clWhite;
  ABitmap.Canvas.Ellipse(0,0,Width,Height);    //hier wird ein Kreis bzw. Ellipse verwendet, der später "frei" bleibt
 
  //Zeichnen
  SetShape(ABitmap);
  ABitmap.Free;         //das war's auch schon
end;
 
Vielleicht ist es für den Einen oder Anderen hilfreich. Hoffentlich hab ich nix vergessen.

Ergänzungen: Leider ist der Hintergrund des Bildes, obwohl .PNG mit transparentem Hintergrund nicht transparent, da Lazarus offensichtlich solche Informationen bei png's ignoriert. Wer diesen weißen Hintergrund durchsichtig machen möchte und/oder unregelmäßige Formen benötigt sei auf den guten Beitrag von RegRunner unter https://www.youtube.com/watch?v=TQrg5agc1ok verwiesen.
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: [Gelöst] Splashscreenanzeige zu kurz

Beitrag von Michl »

Interessant! Habe das eben auch probiert, bei mir gehen auch unregelmäßige Formen (Windows 7, Lazarus 1.5).

Code: Alles auswählen

  TFrmSplash = class(TForm)
    Image1: TImage;
    procedure FormShow(Sender: TObject);
  public
    procedure ShowImage;
  end;
...
procedure TFrmSplash.FormShow(Sender: TObject);
begin
  ShowImage;
end;
 
procedure TFrmSplash.ShowImage;
begin
  SetShape(Image1.Picture.Bitmap);
end;  
Zuletzt geändert von Michl am Do 1. Okt 2015, 21:51, insgesamt 1-mal geändert.

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: [Gelöst] Splashscreenanzeige zu kurz

Beitrag von Michl »

Habe das eben nochmal, entsprechend der allerersten Varianten (die von TBug und mir gemixt) probiert, die Lösung scheint mir doch eleganter (und man braucht die .lpr nicht großartig zu verändern). Damit werden die Formulare ganz normal ohne Verzögerung geladen und die Anzeige ist ebenso mit einer Unform möglich (Windows only).

- eine Form (FrmSplash) erstellen und FormStyle fsStayOnTop, BorderStyle bsNone und Autosize = True wählen
- ein TImage auf das Formular und das TImage Autosize = True stellen und ein transparentes Image (z.B. png) laden
- ein Timer auf das Formular platzieren

und folgendes im TFrmSplash machen:

Code: Alles auswählen

procedure TFrmSplash.FormShow(Sender: TObject);
begin
  SetShape(Image1.Picture.Bitmap);
end;
 
procedure TFrmSplash.Timer1Timer(Sender: TObject);
begin
  close;
end;  
die und der Code in der .lpr könnte dann so aussehen:

Code: Alles auswählen

begin
  RequireDerivedFormResource := True;
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.CreateForm(TFrmSplash, FrmSplash);
  FrmSplash.Show;  // <- hier Splashscreen anzeigen
  Application.Run;
end.   
Dateianhänge
Splashscreen alternativ.zip
(79.84 KiB) 102-mal heruntergeladen

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Re: [Gelöst] Splashscreenanzeige zu kurz

Beitrag von and4more »

Super, danke für den Tipp
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

and4more
Beiträge: 207
Registriert: Do 15. Nov 2012, 19:13
OS, Lazarus, FPC: Windows 10, Manjaro Linux, Lazarus 1.6.4 (32/64 Bit)
CPU-Target: 32 Bit / 64 Bit

Re: [Gelöst] Splashscreenanzeige zu kurz

Beitrag von and4more »

@Michl
...wie mir gerade aufgefallen ist funktioniert Dein Beispiel nur deshalb so "geschmeidig", weil TForm1 leer ist. Bei einem größeren Programm ist die Anzeige dann etwas holprig. Abhilfe schafft aber wenn man Application.CreateForm(TFrmSplash, FrmSplash); vor die anderen Application-Anweisungen stellt, dann kommt zuerst der Splashscreen und der Rest folgt.
Lazarus 1.6.4 32-Bit + 64-Bit, Windows 10 64-Bit, Manjaro Linux 64-Bit

Antworten