Autor Beitrag
LigH
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 239

Win98SE, Win2000SP4
D7
BeitragVerfasst: Mo 26.02.07 16:05 
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
  1. ausblenden Delphi-Quelltext
    1:
    TForm.OnCreate					

  2. ausblenden Delphi-Quelltext
    1:
    TForm.OnShow					

  3. ausblenden Delphi-Quelltext
    1:
    TForm.OnActivate					

  4. ausblenden Delphi-Quelltext
    1:
    TForm.OnPaint					

  5. ausblenden Delphi-Quelltext
    1:
    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:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
unit MainUnit; 

interface 

uses 
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, 
  Dialogs, ComCtrls, AppEvnts; 

type 
  TfmMain = class(TForm) 
    stbStatus: TStatusBar; 
    aeAppEvents: TApplicationEvents; 
    procedure FormCreate(Sender: TObject); 
    procedure aeAppEventsIdle(Sender: TObject; var Done: Boolean); 
  private 
    { Private-Deklarationen } 
    initializing: Boolean; 
    procedure AutoInit; 
  public 
    { Public-Deklarationen } 
  end

var 
  fmMain: TfmMain; 

implementation 

{$R *.dfm} 

{ TfmMain } 

procedure TfmMain.FormCreate(Sender: TObject); 
begin 
  initializing := true; 
end

procedure TfmMain.AutoInit; 
begin 
  stbStatus.SimpleText := 'Initialisierung'
end

procedure TfmMain.aeAppEventsIdle(Sender: TObject; var Done: Boolean); 
begin 
  if initializing then begin 
    initializing := false; 
    AutoInit; 
  end
  Done := true; 
end

end.


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.


Zuletzt bearbeitet von LigH am Do 01.03.07 08:37, insgesamt 3-mal bearbeitet