Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Form soll sich selbst zerstören (https://www.delphipraxis.net/211807-form-soll-sich-selbst-zerstoeren.html)

iphi 4. Nov 2022 13:58

Delphi-Version: 7

Form soll sich selbst zerstören
 
Hallo,

ich möchte, dass sich mein Form im OnClose-Eventhandler selbst zerstört.
Ich denke, das geht so:

Delphi-Quellcode:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Release;
end;
Das scheint auch zu funktionieren, aber:
Wie finde ich heraus, ob die Form noch da ist oder schon geschlossen wurde und sich zerstört hat???

So gehts jedenfalls nicht:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
if Assigned(Form2) then
  begin
    ShowMessage('Form 2 exists, opening...');
    Form2.Visible:=true;
    Form2.BringToFront;
  end
  else
  begin
    ShowMessage('Form 2 does not exist, creating...');
    Form2:=TForm2.Create(self);
    Form2.Visible:=true;
    Form2.BringToFront;
  end;
end;
Nach release bleibt der Zeiger Form2<>NIL, die Form ist aber nicht mehr im Speicher, d.h. bei erneutem Button1Click folgt unweigerlich die Access Violation.
Wie löse ich das?

dataspider 4. Nov 2022 14:08

AW: Form soll sich selbst zerstören
 
Was stört dich am Standard:
Action := caFree;
?

Delphi.Narium 4. Nov 2022 14:09

AW: Form soll sich selbst zerstören
 
Schonmal in der Hilfe von Delphi 7 nachgeschaut, wofür der Parameter
Delphi-Quellcode:
var Action: TCloseAction
an die Procedur FormClose übergeben wird?
Zitat:

Zitat von Delphi 7 - Hilfe
caFree Das Formular wird geschlossen und sein Speicher freigegeben.

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

KodeZwerg 4. Nov 2022 14:10

AW: Form soll sich selbst zerstören
 
Einfach mal so aus dem Bauch heraus
Delphi-Quellcode:
if ((Form2 <> nil) and (Assigned(Form2))) then

BerndS 4. Nov 2022 14:13

AW: Form soll sich selbst zerstören
 
Die Selbstzerstörung besser so:
Delphi-Quellcode:
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;
Und um herauszufinden, ob das Form2 existiert wäre es besser dieses in Screen.Forms zu suchen.

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
var
  F: TForm;
  I: Integer;
begin
  for I := 0 to Screen.FormCount - 1 do
  begin
    F := Screen.Forms[I];
    if F is TFrom2 then
    begin
      ShowMessage('Form 2 exists, opening...');
      F.Visible:=true;
      F.BringToFront;
      Exit;
    end;
  end;
  ShowMessage('Form 2 does not exist, creating...');
  F:=TForm2.Create(self);
  F.Visible:=true;
  F.BringToFront;
end;
nur hingetippt, nicht getestet!

Die Variable Form2 würde ich löschen.

dataspider 4. Nov 2022 14:15

AW: Form soll sich selbst zerstören
 
Und ob das Form da ist:

Delphi-Quellcode:
function FormExists(AFormClass: TFormClass): Boolean;
Var
  I: Integer;
begin
  Result := False;
  for I := 0 to Screen.FormCount - 1 do
    if (Screen.Forms[I].ClassType = AFormClass) then
    begin
      Result := True;
      Exit;
    end;
end;
// Aufruf:
if FormExists(TForm2) then
...
Ist IMO sicherer als über eine Variable...

iphi 4. Nov 2022 14:28

AW: Form soll sich selbst zerstören
 
Zitat:

Zitat von dataspider (Beitrag 1514319)
Was stört dich am Standard:
Action := caFree;
?

Nichts, das macht aber exakt dasselbe wie Release.

Zitat:

Einfach mal so aus dem Bauch heraus if ((Form2 <> nil) and (Assigned(Form2))) then
Das hilft auch nicht.

Zitat:

procedure TForm1.Button1Click(Sender: TObject);
var
F: TForm;
I: Integer;
begin
for I := 0 to Screen.FormCount - 1 do
begin
F := Screen.Forms[I];
if F is TFrom2 then
begin
ShowMessage('Form 2 exists, opening...');
F.Visible:=true;
F.BringToFront;
Exit;
end;
end;
ShowMessage('Form 2 does not exist, creating...');
F:=TForm2.Create(self);
F.Visible:=true;
F.BringToFront;
end;
Geht, ist aber reichlich umständlich...

Danke!

P.S.
Das Problem liegt meistens zwischen den Ohren! Es gibt gar kein Problem. Ich hatte Form2 nochmal in unit1 deklariert, drum wurde der nie auf NIL gesetzt, schön blöd...

himitsu 4. Nov 2022 14:35

AW: Form soll sich selbst zerstören
 
Wenn ein Objekt sich selbst freigibt, dann darf es außerhalb keine Variablen geben, welche darauf zeigen, bzw. niemand darf mehr darauf zugreifen.

Ausnahme: Das Objekt setzt selbstständig diese (globale) Variable z.B. im Destructor auf NIL, womit dann Prüfungen alla Assigned überhaupt erst funktionieren können.
z.B. im TForm.Destroy ein
Delphi-Quellcode:
Form2 := nil;
oder
Delphi-Quellcode:
if Form2 = Self then Form2 := nil;



Alternativ kann man bei TForm TCustomForm auch im globalen Delphi-Referenz durchsuchenScreen nachsehen, ob es dort aktuell eine Form gibt, welche dem Objektzeiger (und besser optional oder zusätzlich dem gespeicherten ClassType) entspricht.


Seit einer Weile gäbe es auch das [Weak]-Attribut und auch [Unsafe].
Delphi-Quellcode:
var [weak] X: TObject;
, wo Delphi die Variable automatisch auf NIL setzt, wenn das Objekt freigegeben würde, aber Dieses funktioniert nicht überall, bzw. es ist nötig, dass für die jeweilige Platform z.B. ARC vorhanden ist.
https://docwiki.embarcadero.com/RADS...d_Conditionals -> WEAKREF



Zitat:

Delphi-Quellcode:
if ((Form2 <> nil) and (Assigned(Form2))) then

<>nil und Assigned ist das Selbe Gleiche

und es funktioniert nicht, wenn die Variable auf etwas zeigt, was es aber dort nicht mehr gibt.

DeddyH 4. Nov 2022 14:37

AW: Form soll sich selbst zerstören
 
Man muss sich bei der Benutzung der globalen Form-Variablen immer vor Augen halten, dass diese immer nur auf eine Instanz zeigen kann, auch wenn mehrere davon existieren. Wenn man also die Variable Form2 mit nil belegt, hat man möglicherweise die falsche Instanz erwischt und wundert sich anschließend.

TomyN 5. Nov 2022 08:57

AW: Form soll sich selbst zerstören
 
Ich zerstöre in so einem Fall die Form immer extern, d.h. die Form schickt eine 'Zerstörungsanfrage' per Message an ihren Owner und verlässt Close mit action = caNone. Für den Fall, dass der Owner nicht mehr existiert, wird mit action = caFree reagiert.
Daraufhin wird die Form von extern zerstört (der handle muss ja dort vorhanden sein, sonst macht das ganze keinen Sinn) und der Handle auf nil gesetzt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:08 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