Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi MDIChild schließen und sofort wieder öffnen (https://www.delphipraxis.net/177118-mdichild-schliessen-und-sofort-wieder-oeffnen.html)

Tenobaal 17. Okt 2013 14:03

Delphi-Version: 2007

MDIChild schließen und sofort wieder öffnen
 
Hallo Community.
Seit TAGEN sitze ich an dem Problem im Zusammenhang mit dem Schließen und Öffnen von MDIChildren eines Hauptformulars.
Ich habe drei Funktionen/Prozeduren (teilweise hier aus dem Forum) zu meinem Hauptformular hinzugefügt:
  • function TForm_Main.IsFormOpen(Form:TForm) -> Überprüft, ob das Formular "Form" bereits existiert
  • procedure TForm_Main.CloseAllForms; -> Schließt alle Formulare (aber keine MDIChilds) mit Ausnahme des Hauptformulars
  • procedure TForm_Main.CloseAllMDIChilds; -> Schließt alle aktiven MDIChilds

Im folgenden sollen nun über das OnClick-Event des Buttons2 sämtliche Formulare und MDIChilds geschlossen werden. Im OnClick-Event werden deshalb die Proceduren CloseAllForms() und CloseAllMDIChilds() aufgerufen. Danach wird mit IsFormOpen() zu Testzwecken überprüft, ob dass MDIChild FormViewerConfig existiert.

Problem:
Nachdem CloseAllMDIChilds() ausgeführt wurde, werden die MDIChilds nicht SOFORT zerstört, sondern erst nach dem das Button2Click()-Event ausgeführt wurde. Das liegt wohl daran, dass CloseAllMDIChilds() nur das OnClose-Event der Formulare aufruft, aber diese nicht direkt zerstört. Erst nachdem Button2Click()-Event ausgeführt wurde sind diese tatsächlich zerstört und nicht mehr unter Screen.Forms aufgeführt. Wie kann ich die MDIFormulare SOFORT zerstören, aber trotzdem nicht auf das OnClose-Event verzichten?


Delphi-Quellcode:
//Funktion prüft, ob das Formular bereits existiert
function TForm_Main.IsFormOpen(Form:TForm): Boolean;
var
  i: Integer;
begin
  Result := False;
  for i := Screen.FormCount - 1 DownTo 0 do
    if (Screen.Forms[i] = Form) then
    begin
      Result := True;
      Break;
    end;
end;

//Alle Formulare schließen (Ausnahme MDIChild und Form_Main)
procedure TForm_Main.CloseAllForms;
var
  i: Integer;
begin
  for i := Screen.FormCount - 1 DownTo 0 do
    Begin
      If Not(Screen.Forms[i] = Form_Main) And (Screen.Forms[i].FormStyle <> fsMDIChild)  then
      Begin
      Screen.Forms[i].Close;
      End;
    End;
end;

//Alle MDIChilds schließen
procedure TForm_Main.CloseAllMDIChilds;
var
  i: Integer;
begin
  For I := Self.MDIChildCount-1 downto 0 do
  Begin
  Self.MDIChildren[I].Close;
  End;
end;


procedure TForm_Main.Button2Click(Sender: TObject);
begin
  CloseAllForms; //Alle Forms schließen
  CloseAllMDIChilds; //Alle MDIChilds schließen
  If NOT IsFormOpen(FormViewerConfig) then
    Begin
    FormViewerConfig:=TFormViewerConfig.Create(Application, MyMotor);//Formular FormViewerConfig ist weiterhin aktiv, obwohl   FormViewerConfig.Close() bereits ausgeführt wurde. Neue Instanz von FormViewerConfig wird nicht erzeugt.
    End;
End;
Nachtrag:
Wenn ich die Prozedur CloseAllMDIChilds() mit der Zeile "Self.MDIChildren[I].Free;" ergänze wird das MDIChild zerstört. Aber dieses Vorgehen sorgt bestimmt für Probleme, weil Self.MDIChildren[I].Close; auch Free() aufruft, nur zu einem späteren Zeitpunkt?!?

Delphi-Quellcode:
//Alle MDIChilds schließen
procedure TForm_Main.CloseAllMDIChilds;
var
  i: Integer;
begin
  For I := Self.MDIChildCount-1 downto 0 do
  Begin
  Self.MDIChildren[I].Close;
  Self.MDIChildren[I].Free;
  End;
end;

Uwe Raabe 17. Okt 2013 16:22

AW: MDIChild schließen und sofort wieder öffnen
 
Bei dem Close wird dem Form i.A. lediglich eine Message CM_RELEASE per PostMessage in die Message-Queue gestellt. Erst wenn das Form diese Message verarbeitet wird das Free aufgerufen.

Rufst du direkt nach dem Close ein Free auf, erreichst du im Prinzip das gleiche. Die CM_RELEASE Message in der Queue ist dann nicht mehr relevant (ich weiß jetzt nicht, ob die Message entfernt wird oder ob sie einfach ins Leere läuft, weil das Fenster nicht mehr da ist).

Disclaimer: ich kann das jetzt eigentlich nur für XE5 sagen, aber ich denke, daß ist in D2007 genauso.

Bummi 17. Okt 2013 18:38

AW: MDIChild schließen und sofort wieder öffnen
 
Do könntest auf Deinem Template im FormClose-Event Action mit caFree belegen. Z.B.
Delphi-Quellcode:
procedure TTemplate.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  if Formstyle = fsMDIChild then
    Action := caFree;
end;

Uwe Raabe 17. Okt 2013 18:57

AW: MDIChild schließen und sofort wieder öffnen
 
Zitat:

Zitat von Bummi (Beitrag 1232337)
Do könntest auf Deinem Template im FormClose-Event Action mit caFree belegen.

Das hilft aber nicht. Es wird trotzdem Release aufgerufen, was wiederum das PostMessage ausführt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:30 Uhr.

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