![]() |
dynamisch erzeugte Forms richtig freigeben
Hallo zusammen,
vorn weg: ich arbeite mit Delphi 5 (arbeitgeberseitig vorgeschrieben) und bearbeite das Programm eines Kollegen (nicht mehr in der Firma) Ich habe Verständnisprobleme wie er seine dynamisch erzeugten Seiten aufruft und schließt/terminiert? Mein Ziel wäre es, die Seiten auch mit dem "Kreuzchen" schließen zu können ... wie ein Abbrechen-Button. Aber wie ist das genau richtig? Folgendes:
Delphi-Quellcode:
Warum das "Nil" der SpeicherverzeichnisOberfläche, wenn er es erst danach erzeugt? Warum kein "if not Assigned" wie unten beschrieben? Oder ist das nur Programmiererspezifisch?procedure TfrmSplash.btnOKClick(Sender: TObject); ... frmSpeicherverzeichnis:=nil; //warum macht er das? if Speicherverzeichnis='' then begin Application.CreateForm(TfrmSpeicherverzeichnis, frmSpeicherverzeichnis); frmSpeicherverzeichnis.Show; self.Enabled:=False; end; while assigned(frmSpeicherverzeichnis) do begin Application.ProcessMessages; end; if (IRPort=0) or (ArduinoPort=0) then begin Application.MessageBox('Die Schnittstellen konnten nicht ermitteln. '+ 'Schalten Sie den Controller aus um im nächsten Schritt die korrekte '+ 'Erkennung zu gewährleisten.', 'Achtung', mb_OK + mb_ICONWARNING); Application.CreateForm(TfrmPortErkennung, frmPortErkennung); frmPortErkennung.Show; self.Release; exit; end else begin ... Application.CreateForm(TfrmStartseite1B, frmStartseite1B); frmStartseite1B.Show; self.Hide; end; end; end; ______ procedure TfrmSpeicherverzeichnis.btnAbbrechenClick(Sender: TObject); begin self.Release; end; procedure TfrmSpeicherverzeichnis.FormDestroy(Sender: TObject); begin frmSpeicherverzeichnis:=nil; end; Warum das "self.hide" seiner Startoberfläche? Da sind keine Elemente/ Objekte, die er nochmal benutzt. bzw.
Delphi-Quellcode:
procedure TfrmStartseite1B.btnOptionenClick(Sender: TObject);
begin if not Messung.MessungLaeuft then begin Application.CreateForm(TfrmOptionen, frmOptionen); frmOptionen.show; self.Enabled:=False; end else begin Application.MessageBox('Das Fenster kann nur aufgerufen werden, wenn ' + 'aktuell keine Messung läuft.', 'Achtung', mb_OK + mb_ICONWARNING); end; end; ___________ procedure TfrmOptionen.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin CanClose:=False; frmStartseite1B.Enabled:=True; self.Release; if assigned(frmStartseite1B) then begin frmStartseite1B.Enabled:=True; end; if assigned(frmStartseite2B) then begin frmStartseite2B.Enabled:=True; end; end; procedure TfrmOptionen.btnOKClick(Sender: TObject); begin close; end; Ich habe im Forum so viel rausbekommen, dass • Form.close = Form.Visible := false • Form.release = setzt eine Application. Message ab/ gibt aber nix frei • Form.Free ist was anderes als Form.freeAndNil Meine Fragen: • Ist es wirklich sinnvol, die aufrufende Form immer Enabled:=false zu setzen? • Auf manchen Seiten steht bei CloseQuery nur CanClose:=false und beim Abbrechen-Button aber nur close; !? da kann ich doch das CloseQuery weglassen oder? • Mir wiederstrebt es irgendwie die Form nicht in sich selbst zu beenden (Form.CloseQuery)... ist das nicht sauberer reicht es nicht (so hab ich es bisher gemacht ... bin kein Programmierer):
Delphi-Quellcode:
So würde ich jetzt seine Forms anpassen. Da ich mir aber nicht sicher bin, ob das so korrekt ist (mal abgesehen von dem Programmierauffwand) möchte ich hier lieber nochmal nachfragen, wie man das eigentlich richtig macht.
procedure TfrmStartseite.MomentanwerteButtonClick(Sender: TObject);
begin if not Assigned(frmMomentanwerte) then begin Application.CreateForm(TfrmMomentanwerte,frmMomentanwerte); end; frmMomentanwerte.show; frmMomentanwerte.Button2Click(Self); //aktualisiert die Daten end; ______ procedure TfrmMomentanwerte.Button1Click(Sender: TObject); begin close; //Button "zur Startseite" end; procedure TfrmMomentanwerte.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin frmMomentanwerte.Release; frmMomentanwerte := nil; end; ______ procedure TfrmStartseite.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin ... if Assigned(frmMomentanwerte) then frmMomentanwerte.Release; if Assigned(frmKundeneinstellungen) then frmKundeneinstellungen.Release; ... //für alle dynamischen Forms //falls noch was offen ist, wenn das Programm beendet wird ... //andere Variablen wieder freigeben //Messung ist bereits beendet CanClose := true; end; ... Schon mal Danke im Vorraus die Suchende |
AW: dynamisch erzeugte Forms richtig freigeben
Hello :)
Da hast du ja einen ganz schönen Brocken bekommen ... Zitat:
Delphi-Quellcode:
entweder eine globale Variable oder ein Property von
frmSpeicherverzeichnis
Delphi-Quellcode:
ist. Also existiert die Variable über den ganzen Programmablauf. Und er wollte damit wohl sicherstellen, dass der Programmablauf in der nachfolgenden Schleife nicht blockiert wird, wenn
TfrmSplash
Delphi-Quellcode:
schon gesetzt wurde.
Speicherverzeichnis
Weiterhin sieht es so aus, als ob er hier ein
Delphi-Quellcode:
"simuliert". Das lässt der darunterliegende Block vermuten:
ShowModal
Delphi-Quellcode:
Das ist sehr unsauber, da es den gesamten restlichen Programmablauf in der Schleife blockiert.
while assigned(frmSpeicherverzeichnis) do
begin Application.ProcessMessages; end; Warum er hier nicht einfach ...
Delphi-Quellcode:
... verwendet, kann ich aus dem Code jedoch nicht ersehen.
if Speicherverzeichnis='' then
begin frmSpeicherverzeichnis := TfrmSpeicherverzeichnis.Create(Self); frmSpeicherverzeichnis.ShowModal; end; Zitat:
Delphi-Quellcode:
) verstecken will?
frmSplash
Genauso auch hier:
Delphi-Quellcode:
Statt ...
procedure TfrmStartseite1B.btnOptionenClick(Sender: TObject);
begin if not Messung.MessungLaeuft then begin Application.CreateForm(TfrmOptionen, frmOptionen); frmOptionen.show; self.Enabled:=False; end else begin Application.MessageBox('Das Fenster kann nur aufgerufen werden, wenn ' + 'aktuell keine Messung läuft.', 'Achtung', mb_OK + mb_ICONWARNING); end; end;
Delphi-Quellcode:
... kann man (theoretisch) auch ...
Application.CreateForm(TfrmOptionen, frmOptionen);
frmOptionen.show; self.Enabled:=False;
Delphi-Quellcode:
... machen.
frmOptionen := TfrmOptionen.Create(Self);
frmOptionen.ShowModal; Zitat:
Delphi-Quellcode:
Form.close = Form.Visible := false
Jein, nicht ganz.
Delphi-Quellcode:
prüft über
Form.Close
Delphi-Quellcode:
, ob eine Form geschlossen werden kann. Wenn
Form.CloseQuery
Delphi-Quellcode:
Form.CloseQuery
Delphi-Quellcode:
setzt, bleibt die Form offen.
CanClose := FALSE
Delphi-Quellcode:
Form.release = setzt eine Application. Message ab/ gibt aber nix frei
Richtig.
Delphi-Quellcode:
setzt eine Message in die MessageQueue, die "irgendwann" verarbeitet wird und erst dann wird das Fenster geschlossen.
Form.Release
Ich habe aber auch mal gelernt, dass man nicht mit
Delphi-Quellcode:
arbeiten sollte.
Release
Delphi-Quellcode:
Form.Free ist was anderes als Form.freeAndNil
Gibt es
Delphi-Quellcode:
in Delphi 5 wirklich (noch)? Ich habe das jedenfalls hier nicht. Es gibt die Funktion
Form.FreeAndNil
Delphi-Quellcode:
, die eine übergebene Variable des Typs
FreeAndNil(var ObjectReference)
Delphi-Quellcode:
nach dem Freigeben auf
TObject
Delphi-Quellcode:
setzt.
nil
Delphi-Quellcode:
macht also nichts anderes als
FreeAndNil
Delphi-Quellcode:
ObjectReference.Free; ObjectReference := nil
Zitat:
Delphi-Quellcode:
zu arbeiten. Es sei denn es gibt zwingend Gründe, warum man das so machen müsste.
ShowModal
Zitat:
Delphi-Quellcode:
arbeit, er das
Release
Delphi-Quellcode:
"übergeht", um sicherzustellen, dass die Form nur dann geschlossen wird, wenn der Benutzer einen bestimmten Ablauf einhält. Zum Beispiel dass eine Form nicht über das [x] geschlossen werden darf, sondern nur über die zur Verfügung stehenden Buttons.
CloseQuery
Zitat:
Zitat:
Delphi-Quellcode:
procedure TfrmMomentanwerte.FormCloseQuery(Sender: TObject;
var CanClose: Boolean); begin frmMomentanwerte.Release; frmMomentanwerte := nil; end;
Delphi-Quellcode:
sollte nur am Ende
CloseQuery
Delphi-Quellcode:
setzen. Sonst nichts anderes.
CanClose
Wenn es eine globale Variable
Delphi-Quellcode:
gibt, die unbedingt auf
frmMomentanwerte
Delphi-Quellcode:
gesetzt werden muss, dann sollte das entweder in
nil
Delphi-Quellcode:
oder
OnClose
Delphi-Quellcode:
passieren.
OnDestroy
Lange Rede, kurzer Sinn: Das was der ursprüngliche Programmierer da gemacht hat, erscheint mir recht unsauber und "brachial". Aber wie schon gesagt, er wird scheinbar seine Gründe dazu gehabt haben. Jedoch denke ich, dass man das Ganze viel eleganter löser kann, indem man die Formen-Logik nochmal überdenkt und an vielen Stellen
Delphi-Quellcode:
benutzt.
ShowModal
|
AW: dynamisch erzeugte Forms richtig freigeben
Danke nuclearping,
für die ausführliche Antwort. Ich hatte meinem ehemaligen Kollegen auch eine E-Mail geschickt, woraufhin er nur antwortete, dass er nicht über das Kreuzchen schließen lassen will, da "man bei dieser Art des Schließens oft nicht weiß ob der Nutzer getätigte Änderungen übernehmen will oder eben nicht. Daher ist das meist nur über "OK" oder "Abbrechen" möglich." ... Naja, ich bin halt anderer Meinung und habe Probleme damit in desen Verlaufsweg gezwungen zu werden. Ich möchte auch während einer Messung mal Parameter anschauen können ... vielleicht nochmal Diagrammeinstellungen ändern und dann wieder zu Parametern zurückkehren ... vielleicht war es auch nur der mangelnden Zeit geschuldet... Ich werde das mit dem ShowModal mal probieren, ob ich das an diesen Stellen als bedienerfreundlich empfinde. Also wenn ich es jetzt so Mache ist das OK?
Delphi-Quellcode:
Ich will einfach nur, dass meine Resourcen nach dem "Programm schließen" wieder sauber freigegeben werden. Die Forms sind halt dynamisch gedacht und wenn was nicht benutzt wird, muss es ja auch keinen Speicher/Arbeitsspeicher belegen. Ich hab mich mit der Resourcenverwaltung noch nicht weiter beschäftigt. Ich bin meist froh, wenn das Programm macht was es soll. Aber wenigstens die Forms sollten sauber erzeugt und geschlossen werden.
procedure TfrmStartseite.MomentanwerteButtonClick(Sender: TObject);
begin if not Assigned(frmMomentanwerte) then begin Application.CreateForm(TfrmMomentanwerte,frmMomentanwerte); end; frmMomentanwerte.show; frmMomentanwerte.Button2Click(Self); //aktualisiert die Daten end; ______ procedure TfrmMomentanwerte.Button1Click(Sender: TObject); begin close; //Button "zur Startseite" end; procedure TfrmMomentanwerte.FormDestroy(Sender: TObject; //oder kann ich mir das sparen var CanClose: Boolean); begin frmMomentanwerte := nil; end; ______ procedure TfrmStartseite.FormCloseQuery(Sender: TObject; var CanClose: Boolean); begin ... if Assigned(frmMomentanwerte) then begin frmMomentanwerte.Close; //statt Release ... besser als Release? //und anschließend noch "frmMomentanwerte := nil;" wenn es dort nicht in der FormDestroy steht? //oder doch lieber immer ein FormDestroy mit nil? if Assigned(frmKundeneinstellungen) then frmKundeneinstellungen.Release; ... //für alle dynamischen Forms //falls noch was offen ist, wenn das Programm beendet wird ... //andere Variablen wieder freigeben //Messung ist bereits beendet CanClose := true; end; Grüße die Suchende |
AW: dynamisch erzeugte Forms richtig freigeben
Wenn Du dynamische modale Fenster brauchst, geht das eigentlich ganz einfach.
Delphi-Quellcode:
Dazu würde ich die entsprechenden Formulare erstens nicht automatisch erzeugen lassen (scheint ja schon so zu sein) und in deren Units die jeweilige globale Formular-Variable rigoros löschen, da sie nicht gebraucht wird und man so recht schnell merkt, wo überall davon Gebrauch gemacht wird. Dann muss man aber auch daran denken, dass die Buttons auch das ModalResult des Formulars setzen sollten (kann man im Objektinspektor einstellen), sonst funktioniert der obige Code nicht wie erwartet.
procedure TMainForm.ButtonBlubbClick(Sender: TObject);
var frmSettings: TrmSettings; begin frmSettings := TfrmSettings.Create(nil); try //Benutzer hat "OK" geklickt if frmSettings.ShowModal = mrOK then MachWas; finally frmSettings.Free; end; end; |
AW: dynamisch erzeugte Forms richtig freigeben
Danke DaddyH,
ich hab jetzt 'ne Ahnung wie ich's machen kann. Für kleinere Anfragen werde ich demnächst das ShowModal nutzen und wie ich die Antworten auslese, hast du ja auch erklärt :) danke. |
AW: dynamisch erzeugte Forms richtig freigeben
Zitat:
Mit Verlaub, aber dein Kollege erzählt Quatsch: Es liegt am Programmierer, wie ein Programm auf das Schließen eines Formulars in dessen OnClose-Ereignisbehandlung reagiert. Das Ereignis OnClose wird auch dann ausgelöst, wenn der Anwender auf das X in der Titelleiste klickt. Wenn ein modales Fenster unter diversen Bedingungen mit je einem anderem Rückgabe-Wert geschlossen werden soll, spielt das X sowieso keine Rolle, weil bereits beim Setzen von ![]() |
AW: dynamisch erzeugte Forms richtig freigeben
Zitat:
Also weg mit allen BorderIcons und Alt+F4 abfangen, und gut isses. Dann wird auch sauberer Code daraus. |
AW: dynamisch erzeugte Forms richtig freigeben
Zitat:
|
AW: dynamisch erzeugte Forms richtig freigeben
Wozu das "X" deaktivieren? Wird das Fenster einfach geschlossen, ist ModalResult mrNone, bei Abbrechen mrCancel und nur bei Bestätigung mrOK. Wo ist das Problem?
|
AW: dynamisch erzeugte Forms richtig freigeben
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 10:55 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 by Thomas Breitkreuz