AW: (Formular-)Handling größerer Projekte
Zitat:
|
AW: (Formular-)Handling größerer Projekte
Eigentlich kann man sagen, dass bei größeren Projekten die globalen Form-Variablen quasi als non existent zu betrachten sind. Die gibt es einfach nicht mehr.
Sobald von einer Form mehrere Instanzen benötigt werden, hat man eh ein Problem, denn die globale kann ja nur eine Referenz speichern. Also merkt sich der Erzeuger der Form diese Referenz und gibt diese je nach Bedarf wieder frei. |
AW: (Formular-)Handling größerer Projekte
Zitat:
Der Bahnhof ist für mich jedoch noch nicht kleiner geworden. Wenn ich - respektive der User - einen Button zum Schließen hat, dann ist die Sache schon klar. Aber, ich hab doch ausgenommen von modalen Fenstern i.d.R. keinen Close-Button. Darum die Frage, wenn ich denn schon Release verwenden soll, wo? Und wo setzt man die Form-Variable auf nil? Muss ja gemacht werden, sonst müsste ich ja die bisherige Boolean-Variable weiter verwenden. So langsam kommt mir der Verdacht, dass die aus der Not geborene Variante (ich wusste bzw. weiß es ja nicht besser, und sogar die Experten sind sich nicht offensichtlich ganz so einig wie man es besser oder idealerweise macht) mit der Hilfsvariablen gar nicht so schlecht ist. Darum nochmals die Frage: Ist das jetzt der Königsweg? Oder was funktioniert in dieser Variante nicht so wie gewollt? Speicherleck scheint es ja keines zu geben, denn mit FastMM und aktiviertem "ReportMemoryLeaksOnShutdown := True" kommt jedenfalls keine Meldung.
Delphi-Quellcode:
{-Interface-procedure zum Anzeigen der Form-}
procedure FrmClient1_Show; begin if not Assigned(FrmClient1) then FrmClient1 := TFrmClient1.Create(Application); FrmClient1.Show; end; procedure TFrmClient1.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; FrmClient1 := nil; end; procedure TFrmClient1.FormCreate(Sender: TObject); begin // EDIT: Sorry, das braucht man ja nicht mehr FrmClient1Active := true; end; |
AW: (Formular-)Handling größerer Projekte
Zitat:
Mit Action:= caFree wird das Formular geschlossen und der Speicher freigegeben, wie es auch in der von dir zitierten Hilfe steht. Dort steht allerdings nicht, wann und wie diese Freigabe geschieht. Ein Blick in den Quelltext von TCustomForm zeigt, dass dann nach dem Aufruf von OnClose einfach ein Release gemacht wird. Also sind wir uns wieder einig :cheers: |
AW: (Formular-)Handling größerer Projekte
Zitat:
Das hier:
Delphi-Quellcode:
bewirkt genau das selbe wie:
procedure TFrmClient1.FormClose(Sender: TObject; var Action: TCloseAction);
begin Action := caFree; FrmClient1 := nil; end;
Delphi-Quellcode:
Ich habe hier übrigens auch wie du Forms, von denen es nur eine Instanz geben kann. Dabei prüfe ich deren Existenz auch über die Form-Variablen. Bei allen anderen Forms (modale Dialoge etc) lösche ich die von Delphi automatisch erzeugte Form-Variable immer als erstes raus.
procedure TFrmClient1.FormClose(Sender: TObject; var Action: TCloseAction);
begin Action := caNone; FrmClient1 := nil; Release; end; |
AW: (Formular-)Handling größerer Projekte
Chapeau! Bei modalen Fenstern :thumb:
Delphi-Quellcode:
Aber bei "normalen" Fenstern ???
procedure TCustomForm.CloseModal;
var CloseAction: TCloseAction; begin ... case CloseAction of caNone: ModalResult := 0; caFree: Release; end; ... end;
Delphi-Quellcode:
EDIT:
procedure TCustomForm.DoClose(var Action: TCloseAction);
begin if Assigned(FOnClose) then FOnClose(Self, Action); end; Jetzt hab ich's kapiert, und darum werde ich es zukünftig so machen:
Delphi-Quellcode:
Wenn da mal jemand über meinen Code stolpern sollte, sieht man gleich, was passiert.
procedure TFrmClient1.FormClose(Sender: TObject; var Action: TCloseAction);
begin Action := caNone; // In der CustomForm soll nichts passieren FrmClient1 := nil; // Meine Form-Variable ist jetzt ungültig Release; // Ich gebe das Formular selber frei end; Vielen Dank für deine Hilfe und Geduld! |
AW: (Formular-)Handling größerer Projekte
Zitat:
Delphi-Quellcode:
Warum denn noch zwei Schritte machen, welche automatisch gemacht werden?
procedure TFrmClient1.FormClose(Sender: TObject; var Action: TCloseAction);
begin Action := caFree; end; Hat auch den wichtigen Vorteil, dass dies dann auch bei jeder Instanz Deiner Form funktioniert und nicht nur wenn der Zeiger der Instanz auf die globale Variable "FrmClient1" zeigt. |
AW: (Formular-)Handling größerer Projekte
Die modalen Fenster sind ja abgehakt. Es geht ja um nicht modale Fenster. Das ist ja mein aktueller Ansatz (siehe Eröffnung des Thread) aber dann kannst du eben nicht mehr auf "Formvariable = nil" bei der Erstellung prüfen, und brauchst die Hilfsvariable.
Oder du erzeugst mit jedem Aufruf ein neues Formular, anstatt das bestehende anzuzeigen. Wenn du das willst, dann brauchst du ja gar keine Formularvariable:
Delphi-Quellcode:
With TFrmClient1.Create(Application) do Show;
rocedure TFrmClient1.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; end; |
AW: (Formular-)Handling größerer Projekte
Zitat:
Dazu überprüfe ich das Anwendungsobjekt, ob bereits irgendeine Instanz des Fensters erzeugt wurde:
Delphi-Quellcode:
wobei "AFormClass" die Klasse des entsprechenden Fensters ist.
function ShowFormOnce(AFormClass: TComponentClass): TForm;
var liZ1: Integer; begin Result := nil; for liZ1 := 0 to Application.ComponentCount-1 do begin if (Application.Components[liZ1] is AFormClass) then begin Result := TForm(Application.Components[liZ1]); end; end; if (Result = nil) then begin Result := TForm(AFormClass.Create(Application)); end; Result.Show; end; Existiert eine Instanz, dann wird diese angezeigt anderenfalls wird eine Instanz erzeugt und danach angezeigt. |
AW: (Formular-)Handling größerer Projekte
Interessanter Ansatz. Werde ich mal nachverfolgen. Zu deinem Code-Beispiel...da fehlt natürlich noch eine Kleinigkeit:
Delphi-Quellcode:
EDIT: Mal "nachverfolgt". Würde dann so aussehen:
function ShowFormOnce(AFormClass: TComponentClass): TForm;
var liZ1: Integer; begin Result := nil; for liZ1 := 0 to Application.ComponentCount-1 do begin if (Application.Components[liZ1] is AFormClass) then begin Result := TForm(Application.Components[liZ1]); end; end; if (Result <> nil) then begin Result := TForm(AFormClass.Create(Application)); end; if Assigned(Result) then // sonst knallts !!!! Result.Show; end;
Delphi-Quellcode:
Einwände? - Verbesserungsvorschläge?
{-Interface-procedure zum Anzeigen der Form-}
procedure FrmClient1_Show; var i: Integer; begin for i := 0 to Pred(Application.ComponentCount) do if (Application.Components[i] is TFrmClient1) then begin TFrmClient1(Application.Components[i]).Show; Exit; end; with TFrmClient1.Create(Application) do Show; end; procedure TFrmClient1.FormClose(Sender: TObject; var Action: TCloseAction); begin Action := caFree; end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:57 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