Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Form (zur Laufzeit erstellt) richtig schliessen. (https://www.delphipraxis.net/186792-form-zur-laufzeit-erstellt-richtig-schliessen.html)

IMPEGA 30. Sep 2015 13:01

Delphi-Version: 7

Form (zur Laufzeit erstellt) richtig schliessen.
 
Liste der Anhänge anzeigen (Anzahl: 1)
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.

Sir Rufo 30. Sep 2015 13:12

AW: Form (zur Laufzeit erstellt) richtig schliessen.
 
Schau einmal in die Doku
http://docwiki.embarcadero.com/Libra...omForm.OnClose

Hansa 30. Sep 2015 13:46

AW: Form (zur Laufzeit erstellt) richtig schliessen.
 
Damit die Forms den Speicher nicht zumüllen, da reicht das caFree im OnClose völlig aus. Damit das nicht vergessen wird, empfehle ich, eine Musterform zu bauen. Grundlegende Tastatur/Maus/Anzeige-Eigenschaften kann man da auch gut unterbringen. Diese Form dann als Vorlage in die Objektablage verschieben und von da ab vererben. Also nicht sagen : Neu-> Form, sondern Neu->Weitere->Form raussuchen. Richtig gemacht, dann ist zumindest das caFree schon da drin.

nuclearping 30. Sep 2015 14:02

AW: Form (zur Laufzeit erstellt) richtig schliessen.
 
Zitat:

Zitat von IMPEGA (Beitrag 1317318)
Delphi-Quellcode:
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;

Sowas solltest du dir erst garnicht angewöhnen. Es ist nicht nur umständlich, sondern auch extrem wartungs- und erweiterungsunfreundlich.

Hansa 30. Sep 2015 14:08

AW: Form (zur Laufzeit erstellt) richtig schliessen.
 
Zitat:

Zitat von nuclearping (Beitrag 1317329)
Sowas solltest du dir erst garnicht angewöhnen. Es ist nicht nur umständlich, sondern auch extrem wartungs- und erweiterungsunfreundlich.

Was ist genau gemeint ? Was stört Dich ?

nuclearping 30. Sep 2015 14:20

AW: Form (zur Laufzeit erstellt) richtig schliessen.
 
Forms und deren Inhalte per Code erstellen. Oder findest du das etwa praktisch? :D

Das kann man in Delphi doch alles per Form-Designer machen und dann statt ellenlangen redundanten Spaghetticode zu schreiben, einfach die Form dort instanzieren wo man sie braucht und dann am Ende wieder freigeben. Vorallem wenn man (nach einem längeren Zeitraum) mal was ändern / verschieben / hinzufügen will, fängt man an zu suchen und zu basteln.

IMPEGA 30. Sep 2015 14:21

AW: Form (zur Laufzeit erstellt) richtig schliessen.
 
Ui... das ging schnell.
Ich danke Euch.
Ich fühle mich damit bestätigt. Damit kann ich leben.
In der Doku steht es wirklich schwarz auf Weiß.

caFree
Das Formular wird geschlossen und sein Speicher freigegeben.


@nuclearping
Mag ja, sein. Ich hätte aber gerne ein Erklärung wie ich es richtig machen kann.
Ich erstelle unterschiedliche Anzahl an Formen. von 5 bis sagen wir 100 oder sogar mehr.
Ich weiß nicht wie viele ich brauche.
Die Formen sehen Optisch gleich aus, geben aber unterschiedliche Parameter zurück.
Um die Formen untereinander zu unterscheiden bekommt Jede Form ein Logo. Damit weiß ich wo ich bin.
Meine Methode wäre halt ein Mal eine Vorlage zu erstellen und per Parameter Logo und Namen vergeben.
Alles Andere wird immer gleich erstellt. Diese Vorlage habe ich einfach gehalten um es leichter erklären zu können.
Im Endeffekt werden mehrere dynamische Arrays erstellt, aus denen ich je nach Bedarf die Daten übergebe.
Damit habe ich später leichtes Spiel, egal wie viele Formen ich erstellen muss.
Bitte um Tipp falls es anders zu lösen geht. Ich bin für Alles offen.
Jeder Tipp wird gerne gelesen.


Eine Zusatzfrage:
Hat schon Jemand XE10 am laufen?
Gibt es Vorteile zu XE7?
Ich benutze zwar die D7 würde aber eventuell auf neuere Version umsteigen wollen.
Sind die Dateigrößen noch mehr gewachsen? Mich hat es wirklich gestört dass die exe manchmal 30MB groß war.
Selbst im Release sind die Dateien richtig groß.

Hansa 30. Sep 2015 14:43

AW: Form (zur Laufzeit erstellt) richtig schliessen.
 
Zitat:

Zitat von nuclearping (Beitrag 1317335)
Forms und deren Inhalte per Code erstellen. Oder findest du das etwa praktisch? :D

Das kann man in Delphi doch alles per Form-Designer machen und dann statt ellenlangen redundanten Spaghetticode zu schreiben, einfach die Form dort instanzieren wo man sie braucht und dann am Ende wieder freigeben. Vorallem wenn man (nach einem längeren Zeitraum) mal was ändern / verschieben / hinzufügen will, fängt man an zu suchen und zu basteln.

Ja, da stimme ich voll zu. Das ist brotlose Kunst ohne Sinn. Aber es gibt Ausnahmen : ich habe z.B. hier ein Touchscreen Programm. Da ich nun aber das Sortiment zur Designzeit nicht weiss,bleibt mir nichts anderes übrig, als diesen Touchscreen, also die einzelnen Felder zur Laufzeit zu bestücken (aus Datenbank). Da muss ich dann tatsächlich für die einzelnen "Tasten" die Koordinaten und sonstiges setzen. Es ist entsetzlich.

Und hierzu :

Zitat:

Die Formen sehen Optisch gleich aus, geben aber unterschiedliche Parameter zurück.
sag ich nochmals : Objektablage. Aber ich sags gleich : im Internet danach suchen, das bringt nichts, weil das seltsamerweise keiner verwendet (ausser mir). Nicht mal Marco Cantu hat dafür eine Erklärung. :shock:

Jumpy 30. Sep 2015 15:07

AW: Form (zur Laufzeit erstellt) richtig schliessen.
 
Wenn die Forms optisch gleich aussehen, also die selben Button haben und so, dann ist es doch wirklich einfacher so eine Form nur 1x zu erstellen und dann verändert man nur die Sachen, die anders sind von aussen ala

Form:=MyForm.Create(self);
MyForm.Logo:=Irgendwas;

nuclearping 30. Sep 2015 15:13

AW: Form (zur Laufzeit erstellt) richtig schliessen.
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von IMPEGA (Beitrag 1317336)
Mag ja, sein. Ich hätte aber gerne ein Erklärung wie ich es richtig machen kann.

Wie schon gesagt, per Form-Designer.

In deinem Projekt, Datei -> Neu -> VCL-Formular (so heisst es zumindest hier bei mir). Kann sein, dass es in D7 nur Datei -> Neu ... gibt und du dann dort ein Fenster bekommst, wo du Reiter, usw. hast.

Du erstellst eine neue Form und packst da deine Komponenten drauf und speicherst das Ganze ab und instanzierst die Form da wo du sie brauchst.

Ich hab mal mein altes Delphi 6 entstaubt (*hust*) und dir ein Demo-Projekt angehangen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:50 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz