Hi
Vorne mal weg. Ich lerne Delphi über Probieren, Testen und Fragen stellen.
Ich versuche eine Form die ich zur
Laufzeit erstelle richtig schließen und aus dem Speicher entfernen.
Das hier ist nur eine Vorlage, es geht hauptsächlich nur darum die neue zur
Laufzeit erstellte Form aus dem Speicher zu löschen.
Im Projekt werden viele Forms erstellt, die dürfen nicht Modal erstellt werden.
Das ganze habe ich versucht in einer Class zu packen, wegen den Events.
Nun zum Problem.
Möglicherweise ist Alles OK. Ich kann es aber nicht selbst beurteilen. Für mich ist der Speicher frei wenn ich FreAndNil oder Form.Free benutze.
Ich habe in der Form1 ein Button zum testen hinzugefügt. Damit kann ich es leicht erledigen.
Nun komme ich zu der Frage.
In der zur
Laufzeit erstellten Form habe ich ein Button (EXIT) erstellt.
Mit diesem Button möchte ich die Form schließen und den Speicher freigeben.
Ich gehe davon aus dass in meinem Fall der destructor es erledigen soll.
ich kriege aber immer eine Fehlermeldung.
Im Netz habe ich einiges gefunden, das habe ich mir zusammengebastelt.
Allerdings habe aber keine Ahnung ob der Speicher damit freigegeben wird.
Wenn ich Debugge wird bei Exit der destructor nicht abgerufen.
Wenn ich es von Form1 tue allerdings schon.
Bitte ein Mal drüber schauen und Tipp geben wie es richtig geht. Bzw. beurteilen ob es korrekt ist.
Ich kann die Form nicht Modal
erstellen, die sollte aber beim Exit zerstört werden und der Speicher frei sein.
Bitte auch die eine Frage im Quellcode beachten.
//Muss ich hier einzelne Komponenten freigeben ???
// oder reicht es Form.Free ???
Unit1
Delphi-Quellcode:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 =
class(TForm)
ButtonForm_2: TButton;
Memo1: TMemo;
ButtonFrei: TButton;
ButtonForm_3: TButton;
procedure ButtonForm_2Click(Sender: TObject);
procedure ButtonFreiClick(Sender: TObject);
procedure ButtonForm_3Click(Sender: TObject);
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
uses ClassForm;
{$R *.dfm}
var
Form_2 : TFormNeu;
//Test. Damit ich den Speicher von Form1 freigeben kann
Form_3 : TFormNeu;
//Test. Damit ich den Speicher von Form1 freigeben kann
procedure TForm1.ButtonForm_2Click(Sender: TObject);
var
Logo :
string;
Liste : TStringList;
begin
Liste := TStringList.Create;
Liste.Add('
Form2');
Liste.Add('
Titel der Form2');
Logo := '
Logo2';
Form_2 := TFormNeu.Create(Logo,Liste);
try
Form_2.Erstellen;
Memo1.Lines.AddStrings(Form_2.ListeAusgang);
//Übernahme der Parameter von neuen Form beim Erstellen
finally
//...
end;
ButtonForm_2.Enabled := False;
Liste.Free;
end;
procedure TForm1.ButtonForm_3Click(Sender: TObject);
var
Logo :
string;
Liste : TStringList;
begin
Liste := TStringList.Create;
Liste.Add('
Form3');
Liste.Add('
Titel der Form3');
Logo := '
Logo3';
Form_3 := TFormNeu.Create(Logo,Liste);
try
Form_3.Erstellen;
Memo1.Lines.AddStrings(Form_3.ListeAusgang);
//Übernahme der Parameter von neuen Form beim Erstellen
finally
//...
end;
ButtonForm_3.Enabled := False;
Liste.Free;
end;
procedure TForm1.ButtonFreiClick(Sender: TObject);
begin
FreeAndNil(Form_2);
FreeAndNil(Form_3);
ButtonForm_2.Enabled := True;
ButtonForm_3.Enabled := True;
end;
end.
unit ClassForm
Delphi-Quellcode:
unit ClassForm;
interface
uses
Classes, SysUtils, Windows, Controls, Graphics, Forms, Dialogs, StdCtrls;
type
TFormNeu =
class
private
Form : TForm;
GroupBoxArt : TGroupBox;
Radio1 : TRadioButton;
Radio2 : TRadioButton;
ButtonRadioWahl : TButton;
OkButton : TButton;
CancelButton : TButton;
FormNeuEdit : TEdit;
FormNeuLabel : TLabel;
FListeEingang : TStringList;
FListeAusgang : TStringList;
function Aufgabe:
string;
virtual;
procedure NeuerWert(Sender : TObject);
procedure WertSenden(Sender : TObject);
procedure Exit(Sender : TObject);
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
public
constructor Create(Logo:
String;
const Liste: TStringList);
destructor Destroy;
override;
property Erstellen :
string read Aufgabe;
property ListeAusgang : TStringList
read FListeAusgang;
end;
implementation
uses Unit1;
constructor TFormNeu.Create(Logo:
string;
const Liste: TStringList);
begin
inherited Create;
FListeAusgang := TStringList.Create;
FListeEingang := TStringList.Create;
FListeEingang.AddStrings(Liste);
end;
destructor TFormNeu.Destroy;
begin
inherited Destroy;
FListeEingang.Free;
FListeAusgang.Free;
//Muss ich hier einzelne Komponenten freigeben ???
// oder reicht es Form.Free ???
Form.Free;
end;
function TFormNeu.Aufgabe :
string;
begin
Form := TForm.Create(Form1);
with Form
do
begin
BorderStyle := bsDialog;
Width := 350;
Height := 322;
Left := Form1.Left + Form1.Width;
Top := Form1.Top;
Caption := FListeEingang.Strings[1];
OnClose := FormClose;
Show;
end;
GroupBoxArt := TGroupBox.Create(Form);
with GroupBoxArt
do
begin
Parent := Form;
Caption := '
Wert-Wahl';
Width := 342;
Height := 59;
Left := 1;
Top := 4;
Show;
end;
Radio1 := TRadioButton.Create(Form);
with Radio1
do
begin
Parent := GroupBoxArt;
Checked := True;
Caption := '
Wert1';
Left := 8;
Top := 21;
Show;
end;
Radio2 := TRadioButton.Create(Form);
with Radio2
do
begin
Parent := GroupBoxArt;
Checked := False;
Caption := '
Wert2';
Left := 8;
Top := 37;
Show;
end;
ButtonRadioWahl := TButton.Create(Form);
with ButtonRadioWahl
do
begin
Parent := GroupBoxArt;
Caption := '
Wert aktivieren';
Width := 100;
Height := 18;
Left := 94;
Top := 37;
OnClick := NeuerWert;
Show;
end;
FormNeuLabel := TLabel.Create(Form);
with FormNeuLabel
do
begin
Width := Form.Width - 50;
Height := 20;
Left := 15;
Top := 200;
Caption := '
Label für sonstwas';
Parent := Form;
end;
FormNeuEdit := TEdit.Create(Form);
with FormNeuEdit
do
begin
Width := Form.Width - 50;
Height := 20;
Left := 15;
Top := 225;
Text := FListeEingang.Strings[0];
Parent := Form;
//PasswordChar := '*';
end;
OkButton := TButton.Create(Form);
with OKButton
do
begin
Width := 80;
Height := 25;
Left := FormNeuEdit.Left;
Top := FormNeuEdit.Top + FormNeuEdit.Height + 10;
Caption := '
OK';
Parent := Form;
Default := True;
OnClick := WertSenden;
end;
CancelButton := TButton.Create(Form);
with CancelButton
do
begin
Width := 80;
Height := 25;
Left := FormNeuEdit.Left + FormNeuEdit.Width - 80;
Top := FormNeuEdit.Top + FormNeuEdit.Height + 10;
Caption := '
EXIT';
Parent := Form;
OnClick := Exit;
Cancel := True;
end;
try
try
FListeAusgang.Add(FormNeuEdit.Text);
//Beim Erstellen der Form gebe ich paar Parameter zurück
except
on E:
Exception do Result := '
Fehler: ' + E.
Message;
end;
finally
//...
end;
end;
procedure TFormNeu.NeuerWert(Sender : TObject);
begin
if Radio1.Checked
then
ShowMessage('
Wert1')
else
ShowMessage('
Wert2');
end;
procedure TFormNeu.WertSenden(Sender : TObject);
begin
Form1.Memo1.Lines.Add(FormNeuEdit.Text);
// Hiermit übergebe ich etwas an die Memo1 in Form1.
end;
procedure TFormNeu.Exit(Sender : TObject);
begin
Form1.ButtonForm_2.Enabled := True;
Form1.ButtonForm_3.Enabled := True;
TForm(Form).Close;
{Damit schliesse ich die zur Laufzeit erstellte Form}
end;
procedure TFormNeu.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
inherited;
Action := caFree;
end;
end.
Testprojekt ist angehängt.