Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Ist Fenster schon geschlossen?! (speziell: MDI-Fenster) (https://www.delphipraxis.net/106234-ist-fenster-schon-geschlossen-speziell-mdi-fenster.html)

s.h.a.r.k 7. Jan 2008 18:12


Ist Fenster schon geschlossen?! (speziell: MDI-Fenster)
 
Hallo,

ich hoffe mit kann jemand weiterhelfen: ich hab bisher keinerlei Event oder Funktion gefunden, die genau dann ausgeführt wird, wenn ein Fenster (in meinem Fall ein MDI-Child) geschlossen wurde. Ich habe es bisher den folgenden, eher unsauberen Weg gewählt:

Beim OnCloseQuery des MDIs eine Methode in der MDI-Parent aufgerufen, die selbst wiederrum die OnClose des MDIs aufruft. Ich war hierbei in der Hoffungen, dass wenn OnClose abgeschlossen ist das MDIChild aus dem Speicher entfernt wurde und somit eben nicht mehr vorhanden ist.

Allerdings tritt genau an dieser Stelle ein Problem auf, denn selbst nach dem OnClose des MDIChilds exisitert das Child in MDIChildCount noch. Warum tut es das? Zugreifen kann ich nicht mehr darauf, da ich dann einen Zugriffsfehler erhalte. Wo liegt dann mein Problem? Ich hoffe ihr könnt mir hierbei helfen.

BTW(1): Ich kann das Projekt leider nicht hochladen, da zu viel dran hängt. Ihr wollte ja nicht gleich einen Server installieren, um mein Problem anhand des Projekts nachzuvollziehen *lach*

BTW(2): Gibt es eine Möglichkeit einen eigenen Handler (Fenstermanager) zu schreiben, der die folgenden (hoffentlich ohne nähere Beschreibung erklärenden) Methoden implementiert und dies so ziemlich automatisch macht, ohne, dass ich all zu viel Code dafür schreiben muss, d.h. ich will auch nicht aus dem Hauptformular, sowie auch nicht aus den MDIChilds, die entsprechende Funktion aufrufen müssen:
OnBeforeMDICreate
OnAfterMDICreate
OnMDIActivate
OnBeforeMDIClose
OnAfterMDIClose

Ich hoffe ihr versteh so in etwa was ich hiermit will :mrgreen:

Mit freundlichen Grüßen
der haiiii ;)

shmia 7. Jan 2008 18:23

Re: Ist Fenster schon geschlossen?! (speziell: MDI-Fenster)
 
Zunächst mal wird mit folgendem Code ein MDI korrekt geschlossen:
Delphi-Quellcode:
procedure TMDI_Form.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   if FormStyle = fsMDIChild then
     Action := caFree;
end;
Durch die If-Abfrage kann das MDI-Form auch leicht wieder in ein normales Form geändert werden, ohne dass man am Source viel ändern muss.

Beim Zugriff auf das Property MDIChildCount muss man schwer aufpassen !!
Folgender Code funktioniert nicht:
Delphi-Quellcode:
 // alle MDIs schliesen
 while MDIChildCount > 0 do
   MDIChildren[0].Close;
Dagegen funktioniert Folgendes:
Delphi-Quellcode:
var
  i : Integer;
begin
  for i := MDIChildCount -1 downto 0 do
    MDIChildren[i].Close;

s.h.a.r.k 7. Jan 2008 18:29

Re: Ist Fenster schon geschlossen?! (speziell: MDI-Fenster)
 
Zitat:

Zitat von shmia
Zunächst mal wird mit folgendem Code ein MDI korrekt geschlossen:
Delphi-Quellcode:
procedure TMDI_Form.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   if FormStyle = fsMDIChild then
     Action := caFree;
end;
Durch die If-Abfrage kann das MDI-Form auch leicht wieder in ein normales Form geändert werden, ohne dass man am Source viel ändern muss.

Das ist mir klar und stellt auch nicht das Problem dar.

Zitat:

Zitat von shmia
Beim Zugriff auf das Property MDIChildCount muss man schwer aufpassen !!
Folgender Code funktioniert nicht:
Delphi-Quellcode:
 // alle MDIs schliesen
 while MDIChildCount > 0 do
   MDIChildren[0].Close;
Dagegen funktioniert Folgendes:
Delphi-Quellcode:
var
  i : Integer;
begin
  for i := MDIChildCount -1 downto 0 do
    MDIChildren[i].Close;

Genau hier steckt ja mehr oder weniger das Problem. Ich greife, nachdem ich eine Form geschlossen habe auf diesen Counter zu, wobei dieser eben noch die Form "enthält". Warum ist das allerdings so!? Ich denke, wenn ich ein OnClose einer Form aufrufe, danach dann den Counter abfrage, er doch eigentlich um 1 niedriger sein sollte als zuvor!?

shmia 7. Jan 2008 18:52

Re: Ist Fenster schon geschlossen?! (speziell: MDI-Fenster)
 
Zitat:

Zitat von s.h.a.r.k
Ich greife, nachdem ich eine Form geschlossen habe auf diesen Counter zu, wobei dieser eben noch die Form "enthält". Warum ist das allerdings so!? Ich denke, wenn ich ein OnClose einer Form aufrufe, danach dann den Counter abfrage, er doch eigentlich um 1 niedriger sein sollte als zuvor!?

Der Aufruf von [TForm].Close zerstört das Formular ja noch nicht, sondern caFree veranlasst den Aufruf von Release:
Delphi-Quellcode:
procedure TCustomForm.Release;
begin
  PostMessage(Handle, CM_RELEASE, 0, 0);
end;
Diese Message wird aber erst beim nächsten Application.ProcessMessages verarbeitet.
Also ist das Formular-Objekt noch nicht ganz vernichtet, aber im Prinzip schon zum Tode verurteilt.

Ich würde an deiner Stelle einen Callback Mechanismus einbauen:
Delphi-Quellcode:
procedure TMDI_Form.FormClose(Sender: TObject; var Action: TCloseAction);
begin
   if FormStyle = fsMDIChild then
   begin
     // sage dem Hauptformular Bescheid, dass ich (= das MDI-Child) geschlossen werden
     (Owner as TMainForm).MDIClosing(self);
     Action := caFree;
   end;
end;

procedure TMainForm.MDIClosing(f:TcustomForm);
begin
  // das Hauptformular erhält jetzt einen letzten Todesgruss von seinem sterbenden MDI-child
  // so hat man die volle Kontrolle über das Geschehen

  with f as TMDI_Form do
  begin
    if MenuItemAutosave.Checked and DataModified then // DataModified ist ein Property des MDI-Child
      SaveData;          // SaveData ist eine Methode des MDI-Child
  end;
end;

s.h.a.r.k 7. Jan 2008 22:43

Re: Ist Fenster schon geschlossen?! (speziell: MDI-Fenster)
 
Das hatte ich ja schon, hat aber nicht zum gewünschten Ergebnis geführt, jedenfalls nicht so wie ich das haben wollte, muss es aber scheinbar doch so machen.

Hab mir auf der Heimfahrt gerade eben auch noch überlegt, dass ich mir eine eigene Containerklasse für die MDI-Forumlare bauen kann. Zudem bastle ich mir dann noch eine eigene TForm, in der ich dann spezielle Funktionen mit einbaue à la delete etc.

Hatte mir nur vorgestellt, dass es so etwas schon gibt, aber irgendwie ist dies scheinbar nicht so :(


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