[gelöst] Button auslösen im OnShow

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
achim_tecklenburg
Beiträge: 8
Registriert: Mi 4. Mai 2016, 19:51
OS, Lazarus, FPC: Windows (L 1.6 FPC 3.0.0)
CPU-Target: 32Bit
Wohnort: Wien
Kontaktdaten:

[gelöst] Button auslösen im OnShow

Beitrag von achim_tecklenburg »

Hallo Leute,

bin neu hier - Also erstmal viele Grüße an Alle!

Ich habe ein kleines Projekt gestartet, einen Sleep Timer (Source)

Es gibt dort einen Start-Button, der den Count Down auslöst. Die btnStartClick läuft in einer Endlosschleife und fragt über Application.ProcessMessages den Stop-Button ab.
Ich möchte den Button (optional) beim Start des Programms schon auslösen. Doch wenn ich btnStartClick ins OnShow Event des Forms hänge, wird die btnStartClick zwar gestartet, aber das Form wird nicht sichtbar. :|

Was kann man da tun? Ich hatte schon mal versucht die procedure in einem eigenen Thread zu starten, aber das hat nicht auf anhieb funktioniert. Wäre das eine Lösung?

Vielen Dank schonmal - Achim
Dateianhänge
Screenshot
Screenshot
2016-05-04_202320.png (5.96 KiB) 1482 mal betrachtet
Zuletzt geändert von achim_tecklenburg am Sa 7. Mai 2016, 22:51, insgesamt 1-mal geändert.

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

Re: Button auslösen im OnShow

Beitrag von Michl »

Erstmal ein herzliches Willkommen hier im Forum von mir!

Ich habe mir den Code mal angeschaut. Du versuchst das Programm mMn viel zu procedural umzusetzen. Nutze Events, dann funktioniert das auch mit dem Start-Button. Es ist für den Mainthread tödlich ein Sleep(100) in diesen einzubauen.

Nimm lieber einen TTimer von der System-Komponentenpalette und stelle den Intervall auf 100 (und Enabled auf False). Im Eventhander OnTimer lässt du den Code, der jetzt im btnStartClick steht ausführen. Beim btnStartClick startest du nur noch den Timer (Timer1. enabled := True) und wartest, dass dieser alle 100 Millisekunden deinen Code ausführt. Damit sollte dann auch den Mainthread ordentlich abgearbeitet und das Formular angezeigt werden.

PS: im Masterbranch fehlen Dateien. Nicht dass dir damit mal das ganze Projekt zerfliegt.

Code: Alles auswählen

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

achim_tecklenburg
Beiträge: 8
Registriert: Mi 4. Mai 2016, 19:51
OS, Lazarus, FPC: Windows (L 1.6 FPC 3.0.0)
CPU-Target: 32Bit
Wohnort: Wien
Kontaktdaten:

Re: Button auslösen im OnShow

Beitrag von achim_tecklenburg »

Hey Michl,

vielen Dank für die ausführliche Antwort - werd ich gleich mal ausprobieren!

Erwin
Beiträge: 286
Registriert: Mi 16. Sep 2009, 14:15
OS, Lazarus, FPC: Xubuntu 22.04 / x86_64_linux-gtk 2 / L 2.2.0 / FPC 3.2.2

Re: Button auslösen im OnShow

Beitrag von Erwin »

achim_tecklenburg hat geschrieben: Ich möchte den Button (optional) beim Start des Programms schon auslösen. Doch wenn ich btnStartClick ins OnShow Event des Forms hänge, wird die btnStartClick zwar gestartet, aber das Form wird nicht sichtbar. :|
OnShow? So weit ich weiß, wird dann alles darin jedesmal dann ausgelöst, wenn das Formular angeklickt oder in den Vordergrund rückt.
OnCreate (Erstellen) ist meines wissen das Event, wo alles darin dann beim Start ausgeführt wird.
Lazarus 2.2.0 / FP 3.2.4

achim_tecklenburg
Beiträge: 8
Registriert: Mi 4. Mai 2016, 19:51
OS, Lazarus, FPC: Windows (L 1.6 FPC 3.0.0)
CPU-Target: 32Bit
Wohnort: Wien
Kontaktdaten:

Re: Button auslösen im OnShow

Beitrag von achim_tecklenburg »

Danke für den Hinweis mit dem OnShow. Ich hab jetzt extra nochmal nachgelesen, weil ich da auch unsicher war:

FormCreate: Das Form wird angelegt, Speicher alloziert, etc. - Es ist dann aber noch nicht sichtbar.
FormShow: Das Form wird sichtbar geschaltet. Wird nur ausgelöst, wenn es das erste mal sichtbar wird - nicht wenn es in den Vordergrund rückt(!).

Man kann also (wenn ich richtig verstanden hab) entscheiden, ob alle Forms beim Programmstart schon erzeugt und später erst angezeigt werden - Oder ob man das Form erst dann erzeugt wenn es auch angezeigt werden soll.

Edit: Ich hab gerade ausprobiert: Es macht durchaus einen Unterschied, ob man beim Mainform FormShow oder FormCreate verwendet. Wenn ich den Button auslösen will geht das nur im OnShow!

achim_tecklenburg
Beiträge: 8
Registriert: Mi 4. Mai 2016, 19:51
OS, Lazarus, FPC: Windows (L 1.6 FPC 3.0.0)
CPU-Target: 32Bit
Wohnort: Wien
Kontaktdaten:

Re: Button auslösen im OnShow

Beitrag von achim_tecklenburg »

@Michl: Der Hinweis war super! Hab nun die Enlosschleife mit dem Sleep(100) aufgelöst und stattdessen 2 Timer eingeführt:
einer um 10x pro Sekunde den Stop-Button zu checken,
der andere um die Minuten runterzuzählen und die Lautstärkeanpassung auszulösen.

War ziemlich viel Arbeit, aber hat sich gelohnt :D
Der Code ist jetzt viel klarer und den Start Button im OnShow Event auszulösen funktioniert jetzt auch!

Also vielen Dank! :mrgreen:

Edit: Falls es jemandem hilft: Ich musste erst einmal verstehen, dass der TTimer von selbst wie eine Endlosschleife läuft und mit Timer.Enabled = False zum stehen gebracht werden kann. Zuerst hatte ich angenommen, dass er von selbst stoppt und man ihn nach jedem Durchlauf neu starten muss..

SoE
Beiträge: 84
Registriert: Mo 31. Aug 2015, 01:51

Re: [gelöst] Button auslösen im OnShow

Beitrag von SoE »

..und stattdessen 2 Timer eingeführt: einer um 10x pro Sekunde den Stop-Button zu checken...
Wozu braucht man dafür einen extra Timer?
Das Button(OnClick)-Event ist doch schon ein Timer, dafür gibt es das vorgefertigte Event doch... egal ob dein Button nun ein Button ist oder zwei PNG's (TImage)...
..der andere um die Minuten runterzuzählen und die Lautstärkeanpassung auszulösen.
Wird oder ist das ein WindowsProgramm? Dann ist es sicher viel besser einen QueuedTimer zu benutzen, der in einem eigenen Thread läuft. Der normale Timer wird bei hoher Last nicht gefüttert...
Außerdem könntest du überlegen ob du statt des Herunterzählens lieber einmal ausrechnest wie lange bzw. wann etwas ausgeführt/angezeigt werden sollte. Das Ergebnis stellst du dann als Delay im Timer ein. Ist das nicht präziser?... zur Not könnte man auch auf eine bestimmte Uhrzeit prüfen, auch das sollte bei einem normalen Timer präziser sein oder ?

Unter Windows benutzt man eigentlich ab W2000 den QueuedTimer und wenn man 'was visuell verschieben möchte (mit Timer), dann nimmt man den MultimediaTimer. Das bringt sehr viel bessere Ergebnisse.
Probieren geht über Studieren...

achim_tecklenburg
Beiträge: 8
Registriert: Mi 4. Mai 2016, 19:51
OS, Lazarus, FPC: Windows (L 1.6 FPC 3.0.0)
CPU-Target: 32Bit
Wohnort: Wien
Kontaktdaten:

Re: [gelöst] Button auslösen im OnShow

Beitrag von achim_tecklenburg »

Achso - du meinst ich kann im Event des Stop Buttons einfach Timer.enabled := false setzen?
Muss ich mal ausprobieren. Ich glaub ich hab da eine Denkblockade gehabt.

Momentan ist das schon noch ein Windows-Programm. Ich möchte sehr gerne auch ausprobieren auf andere Plattformen zu gehen. Aber da muss ich erstmal rausfinden wie ich die Windows-API Sachen vor dem Compiler "verstecke". So wie es jetzt ist, lässt es sich auf dem Mac z.B. nicht kompilieren. Aber dafür mache ich glaube ich noch mal nen eigenen Thread auf :wink:

Ich nehme also an der QueuedTimer funktioniert nur unter Windows? Ich bin da grad noch auf zwei andere Timer gestoßen
http://wiki.freepascal.org/Yet_another_Running_Timer
http://wiki.freepascal.org/EpikTimer
- muss ich auch mal ausprobieren. Ich merk schon: mit jeder Antwort aus dem Forum muss ich wieder alles umschreiben. :x Aber das ist irgendwie ja auch Sinn der Sache. :)

Zum runterzählen: Ich will die verbleibenden Minuten visuell anzeigen. Dafür muss ich halt schon immer alle 60 Sekunden die Anzeige aktualisieren. Und für die Lautstärkeregelung wird auch 1x pro Minute angepasst.

Also vielen Dank - hab nun wieder einiges zum ausprobieren / umschreiben.

Antworten