Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   2. Form schliessen Variable=Nil (https://www.delphipraxis.net/162425-2-form-schliessen-variable%3Dnil.html)

ibp 22. Aug 2011 17:07

2. Form schliessen Variable=Nil
 
Hallo,

ich glaube heute ist es zu warm.... oder ich sehe den Wald vor Bäumen nicht usw... daher brauche ich kurz Hilfe....

Szenario bisher: Form_1 erstellt zur Laufzeit eine Form_2 und zwar modal. Schön und gut. Saubere Sache.
Delphi-Quellcode:
unit1:
...
Form2:=Tform.Create(nil);
try
  Form2.ShowModal;
finally
  FreeAndNil(Form2);
end;
...

Szenario jetzt: Die Form2 soll nicht mehr modal sein, kann aber jederzeit selber geschlossen oder erstellt werden oder Inhalte ändern sich oder wird bei Programmende einfach mit geschlossen. Form2 darf, wenn nur einmal existieren.

Mein Problem gerade. Wenn die Form2 geschlossen wird dann bekommt unit1 das nicht mit und die Variable Form2 ist noch assigned, auch wenn in Form2 unter FormClose Action:=caFree; eingestellt ist.

Delphi-Quellcode:
unit1:
uses uForm2,...

Form2:TForm2;
...
procedure TForm1.btnCreateForm2Click(Sender: TObject);
begin
  if Assigned(Form2) then <--- hier knallts beim 2. Aufruf wenn Form2 geschlossen wurde, da Form2<>Nil ist!
  begin
    ShowMessage('schon da!');
    Form2.BringToFront;
  end
  else
  begin
    Form2:=TForm2.Create(nil);
    Form2.Show;
  end;
end;

...

procedure TForm1.DingeDieDieWeltNichtBraucht;
begin
  ...
  Form2.ZeigeWasAnderes;
  ...
end;
Wie setze ich Form2=nil wenn der Anwender das Form_2 schliesst?

Ich möchte aber nicht FindComponent nutzen...

Danke schon mal....

jaenicke 22. Aug 2011 17:08

AW: 2. Form schliessen Variable=Nil
 
Setze Form2 einfach in OnDestroy von TForm2 auf nil. ;-)

ibp 22. Aug 2011 17:52

AW: 2. Form schliessen Variable=Nil
 
Zitat:

Zitat von jaenicke (Beitrag 1118664)
Setze Form2 einfach in OnDestroy von TForm2 auf nil. ;-)

haut nicht hin.. Bekomme ich beim Aufruf eine AV. Assigned(Form2)<>Nil!

WM_CLOSE 22. Aug 2011 18:38

AW: 2. Form schliessen Variable=Nil
 
setze in OnCreate/OnDestroy eine Klassenvariable auf true/false. Die kannst du dann abfragen.

Chemiker 22. Aug 2011 19:45

AW: 2. Form schliessen Variable=Nil
 
Hallo,

das Form2 ist in den Optionen auf verfügbar eingestellt?

Bis bald Chemiker

ibp 22. Aug 2011 19:51

AW: 2. Form schliessen Variable=Nil
 
Zitat:

Zitat von Chemiker (Beitrag 1118689)
das Form2 ist in den Optionen auf verfügbar eingestellt?

Ja ... ich kann leider nicht nur mit "Ja" antworten, da es anscheinend eine zu kurze Antwort ist! :roll:

Habe das jetzt so gelöst...

Delphi-Quellcode:
unit1;
..
type
  TForm1 = class(TForm)
    btnCreate: TButton;
    btnTest: TButton;
    procedure FormDestroy(Sender: TObject);
    procedure btnCreateClick(Sender: TObject);
    procedure btntestClick(Sender: TObject);
  private
    { Private-Deklarationen }
    Form2:TForm2;
  public
    { Public-Deklarationen }
  end;

..

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Form2.free;
end;

procedure TForm1.btnCreateClick(Sender: TObject);
begin
  if Assigned(Form2) then
  begin
    Form2.BringToFront;
  end
  else
  begin
    Form2       := TForm2.Create(nil);
    Form2.PFree := @Form2;
    Form2.Show;
  end;
end;

////////////////////////////////////////////////////////

unit2;
..
type
  TForm2 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormDestroy(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
    PFree: ^TForm; // Adresse von
  end;

..

procedure TForm2.FormCreate(Sender: TObject);
begin
  PFree:=nil;
end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action:=caFree;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  if Assigned(PFree) then
  begin
    PFree^:=nil;
  end;
end;

jaenicke 22. Aug 2011 19:56

AW: 2. Form schliessen Variable=Nil
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von ibp (Beitrag 1118668)
Zitat:

Zitat von jaenicke (Beitrag 1118664)
Setze Form2 einfach in OnDestroy von TForm2 auf nil. ;-)

haut nicht hin.. Bekomme ich beim Aufruf eine AV. Assigned(Form2)<>Nil!

Keine Ahnung wie du das machst, bei mir geht das problemlos. Siehe Anhang.

Aber eine andere Frage: Wozu zerstörst du das Formular eigentlich immer wieder? Es reicht doch, es bei der ersten Verwendung zu erstellen und danach einfach sichtbar oder unsichtbar zu machen.

Luckie 22. Aug 2011 20:01

AW: 2. Form schliessen Variable=Nil
 
Na ja, wenn ich es schon dynamisch erstelle, dann auch richtig. Ansonsten kann ich in den Projektoptionen ja auch einstellen, dass es gleich erzeugt werden soll. Aber warum den Speicher unnütz belasten, wenn es nicht gebraucht wird?

ibp 22. Aug 2011 20:04

AW: 2. Form schliessen Variable=Nil
 
Zitat:

Zitat von jaenicke (Beitrag 1118697)
Zitat:

Zitat von ibp (Beitrag 1118668)
Zitat:

Zitat von jaenicke (Beitrag 1118664)
Setze Form2 einfach in OnDestroy von TForm2 auf nil. ;-)

haut nicht hin.. Bekomme ich beim Aufruf eine AV. Assigned(Form2)<>Nil!

Keine Ahnung wie du das machst, bei mir geht das problemlos. Siehe Anhang.

Ja, der Unterschied liegt wohl bei den Optionen und den verfügbaren Formularen (Danke @Chemiker!)

Bei mir stehen die Formulare in den Optionen auf verfügbar!

Zitat:

Zitat von jaenicke
Aber eine andere Frage: Wozu zerstörst du das Formular eigentlich immer wieder? Es reicht doch, es bei der ersten Verwendung zu erstellen und danach einfach sichtbar oder unsichtbar zu machen.

Weil sie nicht immer gebraucht werden! Es kann sein, dass jemand das Fenster 10 mal beim arbeiten benutzt oder aber auch überhaupt nicht!

Chemiker 22. Aug 2011 20:13

AW: 2. Form schliessen Variable=Nil
 
Hallo ipg,


reicht es nicht das Form2 statt mit From2.free einfach mit FreeAndNil(Form2) freizugeben?

Bis bald Chemiker

ibp 22. Aug 2011 20:22

AW: 2. Form schliessen Variable=Nil
 
Zitat:

Zitat von Chemiker (Beitrag 1118704)
reicht es nicht das Form2 statt mit From2.free einfach mit FreeAndNil(Form2) freizugeben?

unit2 hat keinen Zugriff auf Variablen der unit1!

Schau mal hin wo ich Form2.free ausführe! ;-)

Chemiker 22. Aug 2011 20:44

AW: 2. Form schliessen Variable=Nil
 
Hallo ibp,

das Problem ist, dass Du in Form2.FormClose mit Action := caFree; den Speicher frei gibst, aber in Form1 noch auf das Form2 zeigt das nicht mehr vorhanden ist. Wenn Du das weglässt kannst Du doch jederzeit in Form1 mit FreeAndNil (Form2) das Form aus dem Speicher löschen und hast Form2 auf Nil gesetzt und kannst es anschließend wieder neu erzeugen.

Bis bald Chemiker

ibp 22. Aug 2011 20:51

AW: 2. Form schliessen Variable=Nil
 
Zitat:

Zitat von Chemiker (Beitrag 1118718)
...das Problem ist, dass Du in Form2.FormClose mit Action := caFree; den Speicher frei gibst, aber in Form1 noch auf das Form2 zeigt das nicht mehr vorhanden ist. Wenn Du das weglässt kannst Du doch jederzeit in Form1 mit FreeAndNil (Form2) das Form aus dem Speicher löschen und hast Form2 auf Nil gesetzt und kannst es anschließend wieder neu erzeugen.

Ja genau das war ja das Problem, wenn Form2 durch den "X"-Button geschlossen wird und nur durch den kann Form2 in diesem Fall geschlossen werden, dann zeigt in unit1 die Variable Form1 natürlich noch auf den Speicherbereich und assigned(Form2) ist dann true!

Lemmy 22. Aug 2011 21:04

AW: 2. Form schliessen Variable=Nil
 
Hi,

Zitat:

Zitat von ibp;1118694
[DELPHI
unit1;
..
type
TForm1 = class(TForm)
btnCreate: TButton;
btnTest: TButton;
procedure FormDestroy(Sender: TObject);
procedure btnCreateClick(Sender: TObject);
procedure btntestClick(Sender: TObject);
private
{ Private-Deklarationen }
Form2:TForm2;
public
{ Public-Deklarationen }
end;

..
[/DELPHI]

das dürfte das Problem sein - vermutlich hast Du in Unit2 auch Form2:TForm2 irgend wo stehen und dann hast Du an der Stelle in Unit 1 an der du auf NIL testest 2 Variablen mit dem selben Namen. Das kann dann nur schief gehen..

Grüße

Sir Rufo 22. Aug 2011 22:16

AW: 2. Form schliessen Variable=Nil
 
So wie du das machst wird die Form TForm2 immer doppelt im Speicher vorhanden sein.

Einmal automatisch beim Programmstart und dann immer wieder beim Aufruf.
Irgendwie nicht logisch.

Also das Formular nicht automatisch erzeugen lassen.

Um TForm2 Modal aufzurufen folgender Code:
Delphi-Quellcode:
Procedure TForm1.OpenForm2Modal( Sender : TObject );
Var
  ModForm2 : TForm2;
begin
  ModForm2 := TForm2.Create( Self );
  Try
    ModForm2.ShowModal;
  Finally
    ModForm2.Free;
  end;
end;
Um die globale Variable "Form2" aus der Unit2 beim Free auf Nil zu setzen folgender Code
Delphi-Quellcode:
procedure TForm2.FormDestroy( Sender : TObject );
begin
  If Form2 = Self then
    Form2 := nil;
end;

FredlFesl 22. Aug 2011 22:52

AW: 2. Form schliessen Variable=Nil
 
Muss man nicht 'Release' anstelle von 'Free' aufrufen?

Chemiker 22. Aug 2011 23:41

AW: 2. Form schliessen Variable=Nil
 
Hallo,

@Sir Rufo: Soweit ich das Verstanden habe wollte er kein Modal-Form haben.

Ich würde es einfach so machen:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  if Assigned(TestForm) then
  begin
    ShowMessage('Schon da');
    TestForm.Show;
  end else
  begin
    TestForm:=TForm2.Create(Self);
  end;
end;
Delphi-Quellcode:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  Caption:= 'Form1 - Test';
  Show;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  if Assigned(TestForm) then
  begin
    TestForm:=NIL;
  end;
end;

end.
Bis bald Chemiker

Sir Rufo 23. Aug 2011 03:02

AW: 2. Form schliessen Variable=Nil
 
Zitat:

Zitat von Chemiker (Beitrag 1118747)
Hallo,

@Sir Rufo: Soweit ich das Verstanden habe wollte er kein Modal-Form haben.

Du hast recht ... es war modal und jetzt nicht mehr ... :oops:
Zitat:

Zitat von Chemiker (Beitrag 1118747)
Ich würde es einfach so machen:

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  if Assigned(TestForm) then
  begin
    ShowMessage('Schon da');
    TestForm.Show;
  end else
  begin
    TestForm:=TForm2.Create(Self);
  end;
end;

öhhm ... würde ich so machen
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  if not Assigned( Form2 ) then
    begin
      Form2 := TForm2.Create( Self );
    end
  else
    begin
      ShowMessage( 'Schon da' );
    end;
  Form2.Show;
end;
Zitat:

Zitat von Chemiker (Beitrag 1118747)
Delphi-Quellcode:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
  Caption:= 'Form1 - Test';
  Show;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  if Assigned(TestForm) then
  begin
    TestForm:=NIL;
  end;
end;

end.
Bis bald Chemiker

Das kann aber auch ins Auge gehen, wenn es 2 Instanzen von TForm2 gibt. Darum besser so
Delphi-Quellcode:
procedure TForm2.FormDestroy(Sender: TObject);
begin
  // Nur wenn die aktuelle Instanz mit der in der globalen Variablen "Form2" gespeicherten übereinstimmt
  if Form2 = Self then
  begin
    Form2 := NIL;
  end;
end;

FredlFesl 23. Aug 2011 06:40

AW: 2. Form schliessen Variable=Nil
 
Was passiert, wenn Form2 zwischen Close und Destroy angezeigt werden soll?

Wieso nicht Form2 nicht einfach im FormClose auf Nil setzen?

Weiterhin sollte das Anzeigen und die Logik, ob Form2 schon da ist, in TForm2 selbst implementiert werden. Entweder in einer Class Procedure 'ShowNonModal', oder in einer Funktion, die den Zugriff auf Form2 steuert (Ich würde Letzteres vorziehen)
Delphi-Quellcode:
Function Form2 : TForm2;

Implementation
Var
  _Form2 : TForm2;

Function Form2 : TForm2;
Begin
  If _Form2 = Nil Then
    _Form2 := TForm2.Create(Nil);
  Result := _Form2;
End;
...
Procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
Begin
  Action := caFree;
  If Self=_Form2 then
    _Form2 := Nil;
End;
Nun kann ich Form2 auch dann anzeigen, wenn es gerade geschlossen, aber noch nicht freigegeben wurde.

[edit]Oh, die Verfeinerung von Sir Rufo fehlt[/edit]

ibp 23. Aug 2011 07:19

AW: 2. Form schliessen Variable=Nil
 
sehe ich das falsch oder nutzt ihr dazu eine globale Variable um in unit2 die Form beim beenden auf NIL zu setzen damit es dann in unit1 vorhanden ist?

Also bei mir ist das so, dass unit2 keinen Zugang zu unit1 hat.


Wie macht das eigentlich TComponentList? Wenn dort ein Objekt sich selber zerstört, dann löscht sie den Eintrag selber. War spät gestern und bin nicht ganz hinter die Logik gestiegen.

Sir Rufo 23. Aug 2011 07:25

AW: 2. Form schliessen Variable=Nil
 
Ich weiß ja nicht mit welchem Delphi du programmierst, aber wenn ich einfach mal ein Formular neu erstelle, dann habe ich da folgenden Code
Delphi-Quellcode:
unit Unit2;

interface

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

type
  TForm2 = class(TForm)
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

end.
und nun rat mal, was die Variable "Form2" ist ... ein globale ;)

Und um von einer anderen Form diese steuern zu können muss ich ja idR dort die Unit einbinden:
Delphi-Quellcode:
unit Unit1;

interface

...

implementation

uses
  Unit2;

...

end.
und somit kennt die Unit1 auch die Variable "Form2"

Chemiker 23. Aug 2011 07:31

AW: 2. Form schliessen Variable=Nil
 
Hallo,

für nichtmodale Forms müssen meiner Meinung eine globale Variabel erzeugt werden, wie soll das sonst funktionieren?

Bis bald Chemiker

ibp 23. Aug 2011 07:33

AW: 2. Form schliessen Variable=Nil
 
@Sir Rufo,

die 2. Form soll dynamisch erzeugt werden und steht in den Optionen nicht unter automatisch erzeugen. Ist es dann wirklich so, dass dann die Variable Form2 in der unit1 direkt ansprechbar ist und wenn sie nil ist dass dann in unit1 übergibt? Was ist mit mehreren Instanzen von der Form2, wenn diese auch aus anderen Units genutzt wird?

@Chemiker habe das ja auch schon gelöst, siehe Post 6

DeddyH 23. Aug 2011 07:36

AW: 2. Form schliessen Variable=Nil
 
Das hat ja nichts damit zu tun, ob es sich um ein Formular handelt oder nicht. Globale Variablen im interface-Abschnitt sind generell von überall erreichbar, sofern die enthaltende Unit eingebunden wird. Willst Du mehrere Instanzen erzeugen, solltest Du Dir diese unbedingt in einer Liste (TObjectList, Array etc.) merken, da die eine Variable ja sonst mit jeder weiteren Instanz überschrieben und die alte Instanz somit unerreichbar wird.

ibp 23. Aug 2011 07:40

AW: 2. Form schliessen Variable=Nil
 
Zitat:

Zitat von DeddyH (Beitrag 1118778)
Das hat ja nichts damit zu tun, ob es sich um ein Formular handelt oder nicht. Globale Variablen im interface-Abschnitt sind generell von überall erreichbar, sofern die enthaltende Unit eingebunden wird. Willst Du mehrere Instanzen erzeugen, solltest Du Dir diese unbedingt in einer Liste (TObjectList, Array etc.) merken, da die eine Variable ja sonst mit jeder weiteren Instanz überschrieben und die alte Instanz somit unerreichbar wird.

Ja schon aber aus verschiedenen units, daher lohnt sich eine Liste nicht, da die unit2 nur temporär und im Bedarfsfall genutzt wird!

DeddyH 23. Aug 2011 07:41

AW: 2. Form schliessen Variable=Nil
 
Dann nimm doch einfach verschiedene Variablen vom Typ TForm2.

Sir Rufo 23. Aug 2011 07:42

AW: 2. Form schliessen Variable=Nil
 
Zitat:

Zitat von Chemiker (Beitrag 1118776)
Hallo,

für nichtmodale Forms müssen meiner Meinung eine globale Variabel erzeugt werden, wie soll das sonst funktionieren?

Bis bald Chemiker

Nein, muss nicht ... ist aber bei den meisten Einsatzzwecken schon erforderlich und darum auch als Default so implementiert.
(Zudem die automatische Erstellung des Formulars genau diese Variable benötigt -> s.u. )
Es reicht ja, wenn alle, die darauf zugreifen wollen den Zugriff haben und wenn diese Zugriffe nur innerhalb einer Unit passieren, dann würde ich keine globale Variable benötigen.

Zitat:

Zitat von ibp (Beitrag 1118777)
@Sir Rufo,

die 2. Form soll dynamisch erzeugt werden und steht in den Optionen nicht unter automatisch erzeugen. Ist es dann wirklich so, dass dann die Variable Form2 in der unit1 direkt ansprechbar ist und wenn sie nil ist dass dann in unit1 übergibt? Was ist mit mehreren Instanzen von der Form2, wenn diese auch aus anderen Units genutzt wird?

@Chemiker habe das ja auch schon gelöst, siehe Post 6

Die automatisch angelegte globale Variable "Form2" kann genau nur eine Instanz beinhalten.
Wenn du mehrere Instanzen benötigst, dann musst du dich um die Verwaltung dieser selber kümmern.
Und ja, wird die Instanz von TForm2 nicht automatisch beim Start erzeugt, dann ist Form2 NIL.

Delphi-Quellcode:
program Test;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1); // <- da passiert die Zuweisung
  Application.CreateForm(TForm2, Form2); // <- und da auch
  Application.Run;
end.

ibp 23. Aug 2011 07:49

AW: 2. Form schliessen Variable=Nil
 
eben und sie soll ja nicht automatisch erzeugt werden, sondern dynamisch im Bedarfsfall!

Spricht denn etwas gegen die Lösung in Post 6?

Ja ich bekenne mich schuldig, ich hätte die Variablennamen anders benennen sollen!

FaTaLGuiLLoTiNe 23. Aug 2011 07:50

AW: 2. Form schliessen Variable=Nil
 
Wenn von dem Formular tatsächlich immer nur eine Instanz zur gleichen Zeit angezeigt werden soll macht der Vorschlag in Beitrag #19 für mich am ehesten Sinn. Das sieht mir wie eine abgewandelte Form des Singleton-Patterns aus.

Sir Rufo 23. Aug 2011 08:02

AW: 2. Form schliessen Variable=Nil
 
Zitat:

Zitat von FredlFesl (Beitrag 1118767)
Was passiert, wenn Form2 zwischen Close und Destroy angezeigt werden soll?

Wieso nicht Form2 nicht einfach im FormClose auf Nil setzen?

Weiterhin sollte das Anzeigen und die Logik, ob Form2 schon da ist, in TForm2 selbst implementiert werden. Entweder in einer Class Procedure 'ShowNonModal', oder in einer Funktion, die den Zugriff auf Form2 steuert (Ich würde Letzteres vorziehen)
<CODE>
Nun kann ich Form2 auch dann anzeigen, wenn es gerade geschlossen, aber noch nicht freigegeben wurde.

[edit]Oh, die Verfeinerung von Sir Rufo fehlt[/edit]

Damit kann ich auch leben :thumb: - hat sogar ein Hauch mehr Charme als meine Variante ;)

ibp 23. Aug 2011 10:51

AW: 2. Form schliessen Variable=Nil
 
so nun fasse ich zusammen...

Aufgabenstellung:

Aus Unit_x wird zu Laufzeit eine Form_Y aus Unit_y erzeugt. Form_Y wird nicht automatisch erzeugt. Aus unit_x kann auf die Form_Y über eine private Variable zugegriffen werden. Die Form_Y kann durch den Schließen-Button nach Bedarf beendet werden, dabei wird die Variable in Unit_x auf Nil gestzt. Unit_y kennt nicht Unit_x. Es können mehrere Instanzen von Form_y aus anderen Units erzeugt werden.

Meine Lösung:
Delphi-Quellcode:
unit Unit1;

interface

uses
  Unit2,

...

type
  TForm1 = class(TForm)
    btnCreate: TButton;
    btnTest: TButton;
    procedure FormDestroy(Sender: TObject);
    procedure btnShowTestFormClick(Sender: TObject);
    procedure btntestClick(Sender: TObject);
  private
    { Private-Deklarationen }
    TestForm:TForm2;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

...

procedure TForm1.FormDestroy(Sender: TObject);
begin
  TestForm.free;
end;

procedure TForm1.btnShowTestFormClick(Sender: TObject);
begin
  TestForm.DoShow(@TestForm);
end;

procedure TForm1.btnTestClick(Sender: TObject);
begin
  if Assigned(TestForm) then
    ShowMessage('TestForm existiert')
  else
    ShowMessage('TestForm nicht existent')
end;
Delphi-Quellcode:
unit Unit2;

type
  TForm2 = class(TForm)
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
    PCallVarAdr:^TForm;
  public
    { Public-Deklarationen }
    constructor Create(AOwner: TComponent; const SelfVarAdr:Pointer); overload;
    procedure DoShow(const SelfVarAdr:Pointer);
  end;

implementation

{$R *.dfm}

constructor TForm2.Create(AOwner: TComponent; const SelfVarAdr:Pointer);
begin
  inherited Create(AOwner);

  PCallVarAdr := SelfVarAdr;

  Show;
end;

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action:=caFree;
end;

procedure TForm2.FormDestroy(Sender: TObject);
begin
  if Assigned(PCallVarAdr) and Assigned(PCallVarAdr^) and (PCallVarAdr^=Self) then
  begin
    PCallVarAdr^:=nil;
  end;
end;

procedure TForm2.DoShow(const SelfVarAdr:Pointer);
begin
  if Assigned(TForm(SelfVarAdr^)) then
  begin
    BringToFront;
  end
  else
  begin
    TForm2.Create(nil,SelfVarAdr);
  end;
end;

Lemmy 23. Aug 2011 11:03

AW: 2. Form schliessen Variable=Nil
 
Hi,

Alternative zu deiner Zeiger-Geschichte wäre das OnDestroy-Event von Form2 auf eine Methode in Form1 umzuleiten und dort das Feld zu nillen:

Delphi-Quellcode:

  if not Assigned(TestForm) then
    TestForm:=TForm2.Create(self);
  TestForm.OnDestroy:=TestFormDestroy;
  TestForm.Show;
...
procedure TForm1.TestFormDestroy(Sender: TObject);
begin
  TestForm:=nil;
end;
Nachteil an der Geschichte wäre, wenn die OnDestroy schon durch was anderes belegt ist - hier könnte man diese Wert allerdings "zwischenspeichern" und dann im TEstFormDestroy aufrufen...

Grüße

Chemiker 23. Aug 2011 11:24

AW: 2. Form schliessen Variable=Nil
 
Hallo ibp,

nur wie willst Du das lösen, wenn Du von Form3 auf das Form2 zugreifen willst und das Form2 noch vorhanden ist?

Bis bald Chemiker

ibp 23. Aug 2011 12:06

AW: 2. Form schliessen Variable=Nil
 
Zitat:

Zitat von Chemiker (Beitrag 1118879)
nur wie willst Du das lösen, wenn Du von Form3 auf das Form2 zugreifen willst und das Form2 noch vorhanden ist?

Als eigene Instanz. Es geht nicht darum, dass mehrere units auf die gleiche Instanz zugreifen, jede bekommt dann seine eigene.

Sir Rufo 23. Aug 2011 12:18

AW: 2. Form schliessen Variable=Nil
 
Also bei der Aufgabenstellung sollte man das vielleicht so lösen:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Unit2;

type
  TForm1 = class( TForm )

  private
    PrivateForm : TForm2;
    procedure SubFormDestroy( Sender : TObject );
    procedure ErzeugeSubForm( Sender : TObject );
...

implementation

procedure TForm1.ErzeugeSubForm( Sender : TObject );
begin
  PrivateForm := TForm2.Create( Self );
  PrivateForm.OnDestroy := SubFormDestroy;
end;

procedure TForm1.SubFormDestroy( Sender : TObject );
begin
  PrivateForm := nil;
end;

Chemiker 23. Aug 2011 12:20

AW: 2. Form schliessen Variable=Nil
 
Hallo ibp,

Zitat:

Form2 darf, wenn nur einmal existieren.
dann habe ich das falsch verstanden.

Bis bald Chemiker

ConnorMcLeod 23. Aug 2011 12:23

AW: 2. Form schliessen Variable=Nil
 
Ich weiss zwar nicht mehr, wo die Idee her ist, aber bei mir funktioniert das so: das bewusste Fenster bekommt einen wohldefinierten Namen - am Besten in einer Konstanten hinterlegt.

Diese Funktion findet ein Fenster mit einem bestimmten Namen:
Delphi-Quellcode:
function FindFormByName(AFormName: string): TForm;
var
  li: integer;
begin
  Result := nil;

  for li:= 0 to Screen.FormCount-1 do
  begin
    if (Screen.Forms[li].Name = AFormName) then
    begin
      Result := Screen.Forms[li];
      break;
    end;
  end;
end;
Diese Funktion aktiviert das Fenster, wenn bereits vorhanden, ansonsten wird es erzeugt:
Delphi-Quellcode:
const
  FORMNAME = 'MeinSuperFenster';
var
  lfrm    : TMyForm; // das zu zeigende Fenster
begin
  lfrm  := TMyForm(FindFormByName(FORMNAME));
  if Assigned(lfrm) then
  begin
    lfrm.Show;
    lfrm.BringToFront;
  end
  else
  begin
    lfrm     := TMyForm.Create(Application);
    lfrm.Name := FORMNAME;
    lfrm.Show;
  end;
Hoffe, das hilft.

ibp 23. Aug 2011 12:28

AW: 2. Form schliessen Variable=Nil
 
@ConnorMcLeod

ich wollte keine Funktion à la FindXYZ nutzen!

ConnorMcLeod 28. Aug 2011 16:18

AW: 2. Form schliessen Variable=Nil
 
nächste Variante:
das zweite Fenster sendet eine userdefined message an seinen Owner (das erste Fenster) im OnDestroy und der Owner reagiert auf diese Message mit dem Nilen der Variable.


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:25 Uhr.

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