Nach Programmstart und Anzeige automatische Routine starten
Sicherlich sind schon viele Leute darauf hereingefallen, irgend etwas im
Form.OnCreate-Handler tun zu wollen, weil der nur einmal beim Programmstart aufgerufen wird, und dann festzustellen, dass zu diesem Zeitpunkt noch nicht das komplette Programm wirklich mit Inhalt existiert, insbesondere noch keine weiteren Fenster. Die Balance zu finden zwischen "nur beim Programmstart" und "erst wenn das Hauptfenster dargestellt wurde" ist nicht leicht ohne ausreichend Hintergrundwissen.
Ich habe mir mal ein paar Abläufe von Programmstarts protokollieren lassen und festgestellt, dass die wichtigsten Ereignisse von
TForm und
TApplicationEvents in der Reihenfolge
- TForm.OnCreate
- TForm.OnShow
- TForm.OnActivate
- TForm.OnPaint
- TApplicationEvents.OnIdle
gestartet werden, und daher folgender Ablauf im Allgemeinen zu funktionieren scheint:
- Es wird eine ApplicationEvents-Komponente in das Hauptformular eingefügt.
- Im TForm.OnCreate-Handler wird lediglich eine "Semaphore" (Boolean-Variable) initialisiert, die ausschließlich nur zum Programmstart true ist, und im Folgenden gleich false gesetzt wird...
- Im TApplicationEvents.OnIdle-Handler (weil erst da alle vorher wichtigen Ereignisse abgearbeitet wurden) wird die gewünschte Routine ausgeführt, falls die Semaphore true ist - nachdem die Semaphore schnellstmöglich wieder auf false gesetzt wurde.
Das könnte dann etwa so aussehen:
Alternativen dazu wären:
- Was ausgeführt werden muss, bevor das Hauptfenster sichtbar wird, kann man (mit Semaphore) auch in TForm.OnShow behandeln. Nutzer-Ereignishandler werden ja bekanntlich ausgeführt, bevor die Standardmethode für dieses Ereignis abgearbeitet wird (also OnShow direkt vor dem Anzeigen).
- Bei Programmen mit nur einem Hauptfenster wird das Ereignis TForm.OnActivate eventuell nur ein einziges Mal ausgelöst. Auch hier wäre eine Absicherung der Einmaligkeit des Aufrufes sinnvoll. Nachteil: Die Routine kollidiert dann zeitlich etwas mit dem ersten TForm.OnPaint, das gerade dabei ist, das Fenster zum ersten Mal darzustellen.
- Ebenfalls sinnvoll und näher am ereignisorientierten Konzept von Windows wäre es, anstatt der Semaphore einen Handler für eine selbst definierte Windows-Message zu schreiben, und der Applikation diese Nachricht im TForm.OnCreate-Ereignis selbst zu schicken. Allerdings erfordert das ein wenig mehr Arbeit mit dem Quelltext, und im Objektinspektor wäre dieser Handler dann wohl nicht unter den Ereignissen zu finden.