Release Free Abort // Form freigeben aus einem Event \\

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
SoE
Beiträge: 84
Registriert: Mo 31. Aug 2015, 01:51

Release Free Abort // Form freigeben aus einem Event \\

Beitrag von SoE »

Hi,

Frage1: Wie kann ich aus einem Event heraus ein Fenster freigeben? Geht das nur mit Close ?
Ich hab' schon oft gelesen, dass das mit Free und Abort oder aber mit Release gehen soll, aber bei mir klappt das nicht. Ich dachte immer CM_RELEASE und RELEASE und caFREE sind absolut identisch, aber wenn ich RELEASE benutze dann schließt sich zwar optisch das Fenster (ShowModal), aber ich kann das aufrufende Fenster danach nicht mehr aktivieren oder einen Button klicken. Wenn ich aber caFREE benutze dann klappt das problemlos. Kann also nicht das Gleiche sein...
Ein Programm beenden ohne Close ist ja sehr einfach: siehe Button2Click...

Gibt es einen Befehl für "Fenster schließen und sofort aus dem Speicher werfen und dabei nicht OnCloseQuery und OnClose beachten" ?
Natürlich muß man das so nicht machen, Close funzt ja sehr gut, aber ich dachte es geht zumindest irgendwie.
EDIT: bei MyForm.Show funzt Release sehr gut...

Folgendes Beispiel:

Code: Alles auswählen

Procedure TForm1.Button1Click(Sender: TObject);
  Var
   MyForm: TForm;
 Begin
  Try
   MyForm             := TForm.Create(Nil);
   MyForm.Height      := 500;
   MyForm.Width       := 500;
   MyForm.Color       := clBlue;
   MyForm.KeyPreview  := True;
   MyForm.OnKeyPress  := @MyKey;
   MyForm.OnClose     := @MyClose;
   //MyForm.Parent      := Form1;
 
   MyForm.ShowModal;
  Finally
   MyForm.Free;
  End;
 End;
 
Procedure TForm1.Button2Click(Sender: TObject);
 Begin
  Form1.Release;
  Application.Terminate;
 End;
 
Procedure TForm1.MyKey(Sender: TObject; Var Key: Char);
 Begin
  If Key = #27
  Then TForm(Sender).Close;
 
  //TForm(Sender).Release;
  //Abort;
 End;
 
Procedure TForm1.MyClose(Sender: TObject; Var CloseAction: TCloseAction);
  Var
   List: TStringlist;
 Begin
  Try
   List:= TStringlist.Create;
   List.Add('Hallo');
   List.SaveToFile('Hallo.txt');
  Finally
   FreeAndNil(List);
  End;
   CloseAction:= caFree;
 End;
Frage2: Wieso verliert MyForm direkt nach der Erstellung den Fokus und läßt sich auch nicht mehr durch anklicken ansprechen wenn ich MyForm.Parent:= Form1; eingebe? Ist das so gewollt?

Warf
Beiträge: 2122
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Release Free Abort // Form freigeben aus einem Event \\

Beitrag von Warf »

SoE hat geschrieben:Hi,

Frage1: Wie kann ich aus einem Event heraus ein Fenster freigeben? Geht das nur mit Close ?
Ich hab' schon oft gelesen, dass das mit Free und Abort oder aber mit Release gehen soll, aber bei mir klappt das nicht. Ich dachte immer CM_RELEASE und RELEASE und caFREE sind absolut identisch, aber wenn ich RELEASE benutze dann schließt sich zwar optisch das Fenster (ShowModal), aber ich kann das aufrufende Fenster danach nicht mehr aktivieren oder einen Button klicken. Wenn ich aber caFREE benutze dann klappt das problemlos. Kann also nicht das Gleiche sein...
Ein Programm beenden ohne Close ist ja sehr einfach: siehe Button2Click...

Gibt es einen Befehl für "Fenster schließen und sofort aus dem Speicher werfen und dabei nicht OnCloseQuery und OnClose beachten" ?
Natürlich muß man das so nicht machen, Close funzt ja sehr gut, aber ich dachte es geht zumindest irgendwie.
EDIT: bei MyForm.Show funzt Release sehr gut...

Folgendes Beispiel:

Code: Alles auswählen

Procedure TForm1.Button1Click(Sender: TObject);
  Var
   MyForm: TForm;
 Begin
  Try
   MyForm             := TForm.Create(Nil);
   MyForm.Height      := 500;
   MyForm.Width       := 500;
   MyForm.Color       := clBlue;
   MyForm.KeyPreview  := True;
   MyForm.OnKeyPress  := @MyKey;
   MyForm.OnClose     := @MyClose;
   //MyForm.Parent      := Form1;
 
   MyForm.ShowModal;
  Finally
   MyForm.Free;
  End;
 End;
 
Procedure TForm1.Button2Click(Sender: TObject);
 Begin
  Form1.Release;
  Application.Terminate;
 End;
 
Procedure TForm1.MyKey(Sender: TObject; Var Key: Char);
 Begin
  If Key = #27
  Then TForm(Sender).Close;
 
  //TForm(Sender).Release;
  //Abort;
 End;
 
Procedure TForm1.MyClose(Sender: TObject; Var CloseAction: TCloseAction);
  Var
   List: TStringlist;
 Begin
  Try
   List:= TStringlist.Create;
   List.Add('Hallo');
   List.SaveToFile('Hallo.txt');
  Finally
   FreeAndNil(List);
  End;
   CloseAction:= caFree;
 End;
Frage2: Wieso verliert MyForm direkt nach der Erstellung den Fokus und läßt sich auch nicht mehr durch anklicken ansprechen wenn ich MyForm.Parent:= Form1; eingebe? Ist das so gewollt?
Formulare die über den Lazarus WYSIWYG Editor erstellt werden sind von der TApplication Komponente gehandhabt, und da einfach ein Free hinzuhauen ist nicht die beste Idee, da TApplication vielleicht noch versuchen wird darauf zuzugreifen.

Was auch noch passieren kann, nehmen wir mal an du gibst die Form mit Free frei, und nach dem EventCall wird noch etwas ausgeführt, Also die Eventaufrufende Prozedur wäre etwas wie das:

Code: Alles auswählen

procedure TMyComp.Foo;
begin
...
  if Assigned(FMyEvent) Then
    FMyEvent(self);
  Self.Bar
...
zwar weiß ich nicht ob es sowas in der Standard LCL gibt, aber es ist nicht ausgeschlossen, grade bei eigenen Komponenten. Würde nun in dem Event ein Free stehen würde das Zwangsläufig zu eine Zugriffsverletzung führen.

Die Methode Release hingegen markiert die Form meines Wissens nach zur Freigabe, also wird die TApplication beim nächsten Event Loop die Form freigeben. Das ist die deutlich bessere Herangehensweise.
Close mit caFree gibt auch die Form frei und funktioniert ähnlich wie Release, nur dass dabei der Umweg über die TForm.Close methode mit dem OnClose Event gemacht wird, also dort kann man sich nicht beim Aufruf von Close entscheiden die Form freizugeben, sondern im Close Event selbst.

Abort hat mit dem ganzen gar nichts zu tun, das ist einfach nur eine Funktion um aus einem Try Block zu springen.

Zur 2ten Frage:
Soweit ich weiß unterstützt Lazarus keine MDI Forms, also das Forms Kinder anderer MDI Forms sein können, daher ist das nicht so wirklich geplant was du machst, TForms haben soweit ich weiß keinen Parent, da sie allerdings von TWinControl abstammen ist dies dennoch implementiert

SoE
Beiträge: 84
Registriert: Mo 31. Aug 2015, 01:51

Re: Release Free Abort // Form freigeben aus einem Event \\

Beitrag von SoE »

@Warf:
Danke für die Antwort.
Soweit ich weiß unterstützt Lazarus keine MDI Forms,
Ach so, kein Problem, ich hab' das auch nicht wirklich gebrauchen wollen, es war mir nur aufgefallen und ich hatte mich etwas gewundert.

Ich wußte nicht, dass es bei einem Modalen Fenster keine Möglichkeit gibt dieses freizugeben ohne den Umweg über Close.
Das hat zumindest bis jetzt noch nie bei mir geklappt.

Bei einem normalen Fenster funktioniert RELEASE sehr gut, also dachte ich mir das es bei ShowModal auch so gehen sollte. Ich hab' auch schon Beispiele in Foren gefunden wo Leute entsprechenden Code gepostet haben.
Auch bei Delphi7 kann ich bis jetzt kein ShowModal verwenden und dann aus einem Event heraus das Modale Fenster freigeben. Ich muß immer erst Close benutzen und kann dann später unter "Finally" RELEASE oder FREE oder FreeAndNil benutzen.
Ich fand das irgendwie komisch... deswegen der Post...

Antworten