HSG |
|
Die Erzeugung der Formularunit und der zugehörigen *.dfm-Datei samt der bequemen Handhabung im Objektinspektor und der Ereigniszuordnung durch Doppelklick kann man haben, wenn man ein neues Fenster mit
erzeugt. In diesem Fall übernimmt aber die Projekt-Datei *.dpr die Erzeugung des Fensters. Will man das vermeiden, so kann man die entsprechenden Zeilen aus der Projektdatei löschen:
program NeuesFormular; uses Forms, uNeuesFormular in 'uNeuesFormular.pas' {Form1}; // uFormular2 in 'uFormular2.pas' {Form2}; {$R *.res} begin Application.Initialize; Application.CreateForm(TForm1, Form1); // Application.CreateForm(TForm2, Form2); Application.Run; end.
Außerdem die Variablenvereinbarung in der Unit 'uFormular2.pas' löschen. Jetzt ist man alle Automatiken los! Den Namen der Klasse kann man ändern, indem man mit dem Objektinspektor den Namen des Formulars ändert.
procedure TForm1.bNeuClick(Sender: TObject); begin fenster := TForm2.Create(Form1); fenster.Visible := true; end;
Manchmal besteht der Wunsch, dass eine Anwendung über mehrere Formulare verfügen soll. So könnte z.B. bei einem Automaten das Setzen der Zustände von einem separaten Kontrollfenster erreicht werden. Bei einem ersten Zugriff wird man eine Referenzvariable vom Typ TForm definieren und wie üblich dynamisch das Objekt erzeugen und vernichten.
... private f : TForm; ... procedure TForm1.bNeuesFormularClick(Sender: TObject); var hStatus : THeapStatus; begin f := TForm.Create(Form1); f.Visible := true; f.Caption := 'Das ist das neue Fenster'; f.Left := 400; f.Top := 250; f.Width := 500; f.Height := 200; // zur Speicherüberwachung hStatus := GetHeapStatus; mAusgabe.Lines.Add(IntToStr(hStatus.TotalAllocated)); end; procedure TForm1.bVernichteClick(Sender: TObject); var hStatus : THeapStatus; begin f.Free; // zur Speicherüberwachung hStatus := GetHeapStatus; mAusgabe.Lines.Add(IntToStr(hStatus.TotalAllocated)); end;
Das funktioniert durchaus wie das Beispiel zeigt:
Es tauchen aber einige neue Fragen auf. So soll das neue Fenster eine eigene Struktur und Funktionalität haben. Das läßt sich durch Aggregation weiterer Unter-Objekte erreichen. Das ist aber nur mit einigem Programmieraufwand zu erreichen. Die neue Klasse könnte z.B. in einer neuen Unit - hier uFormN - beschrieben werden:
unit uFormN; interface uses Forms, Classes, StdCtrls; type TFormN = class(TForm) private bTuewas: TButton; lAusgabe: TLabel; procedure bTuewasClick(Sender: TObject); public constructor create(AOwner : TComponent); end; implementation constructor TFormN.create(AOwner : TComponent); begin inherited CreateNew(AOwner); bTueWas := TButton.Create(self); // self ist die 'eigene Adresse' bTueWas.Left := 24; bTueWas.Top := 16; bTueWas.caption := 'tue was'; bTueWas.parent := self; bTueWas.OnClick := bTueWasClick; // Zuweisung der Ereignisbehandlung; lAusgabe := TLabel.Create(self); lAusgabe.Left := 120; lAusgabe.Top := 24; lAusgabe.caption := '???'; lAusgabe.parent := self; end; procedure TFormN.bTuewasClick(Sender: TObject); begin lAusgabe.caption := 'Hallo Welt!'; end; end.
In obiger Unit fällt auf, dass statt des Konstruktors create createNew verwendet wurde. Den Grund mag folgender Auszug aus der Delphi-Hilfe erläutern:
Diesen ganzen Aufwand kann man sich sparen, wenn man Delphi erlaubt, im Konstruktor Create die uFormN.dfm-Datei einzulesen:
object FormN: TFormN Left = 442 Top = 323 Width = 345 Height = 101 Caption = 'Das ist das neue Fenster' Color = clBtnFace Font.Charset = DEFAULT_CHARSET Font.Color = clWindowText Font.Height = -11 Font.Name = 'MS Sans Serif' Font.Style = [] OldCreateOrder = False PixelsPerInch = 96 TextHeight = 13 object lAusgabe: TLabel Left = 120 Top = 24 Width = 12 Height = 13 Caption = '??' end object bTuewas: TButton Left = 24 Top = 16 Width = 75 Height = 25 Caption = 'tue was' TabOrder = 0 OnClick = bTuewasClick end end
Die Unit uFormN muss dann auch angepasst werden:
unit uFormN; interface uses Forms, Classes, StdCtrls, Controls; type TFormN = class(TForm) bTuewas: TButton; lAusgabe: TLabel; procedure bTuewasClick(Sender: TObject); private public end; var FormN : TFormN; implementation {$R *.dfm} procedure TFormN.bTuewasClick(Sender: TObject); begin lAusgabe.caption := 'Hallo Welt!'; end; end.
Man sieht dreierlei:
Die Erzeugung der Formularunit und der zugehörigen *.dfm-Datei samt der bequemen Handhabung im Objektinspektor kann man haben, wenn man ein neues Fenster mit
erzeugt. In diesem Fall übernimmt aber die Projekt-Datei *.dpr die Erzeugung des Fensters. Will man das vermeiden, so kann man die entsprechenden Zeilen aus der Projektdatei löschen:
program NeuesFormular; uses Forms, uNeuesFormular in 'uNeuesFormular.pas' {Form1}, uFormN in 'uFormN.pas', Unit2 in 'Unit2.pas' {Form2}; {$R *.res} begin Application.Initialize; Application.CreateForm(TForm1, Form1); Application.CreateForm(TForm2, Form2); Application.Run; end.
Bei dieser Gelegenheit erkennt man, dass das Objekt Application anscheinend auch ohne eigenes Zutun zu Beginn schon da ist. Irgendwo muss es ja losgehen!
Es bleibt die Frage zu klären, wer das neue Fenster zur Laufzeit erzeugen soll. Natürlich kann das - wie in obigem Beispiel - durch einen Button geschehen. Meistens wird man eine automatische Erzeugung vorziehen. Es bietet sich an, diese Aufgabe OnCreate des Hauptformulars zu übertragen.
procedure TForm1.FormCreate(Sender: TObject); var hStatus : THeapStatus; begin // zur Speicherüberwachung hStatus := GetHeapStatus; mAusgabe.Lines.Add(IntToStr(hStatus.TotalAllocated)); f := TFormN.Create(Form1); f.visible := true; // zur Speicherüberwachung hStatus := GetHeapStatus; mAusgabe.Lines.Add(IntToStr(hStatus.TotalAllocated)); end;
Bevor man das eventuell fehlende neue Fenster sucht, sollte man auch hinter das Hauptfenster schauen!