AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi dynamisch erzeugte Forms richtig freigeben

dynamisch erzeugte Forms richtig freigeben

Ein Thema von die Suchende · begonnen am 1. Jul 2015 · letzter Beitrag vom 3. Jul 2015
Antwort Antwort
Seite 1 von 4  1 23     Letzte » 
die Suchende

Registriert seit: 27. Mär 2009
16 Beiträge
 
#1

dynamisch erzeugte Forms richtig freigeben

  Alt 1. Jul 2015, 15:47
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:
    
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 "Nil" der SpeicherverzeichnisOberfläche, wenn er es erst danach erzeugt? Warum kein "if not Assigned" wie unten beschrieben? Oder ist das nur Programmiererspezifisch?

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:
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;
...
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.


Schon mal Danke im Vorraus
die Suchende
  Mit Zitat antworten Zitat
nuclearping

Registriert seit: 7. Jun 2008
708 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: dynamisch erzeugte Forms richtig freigeben

  Alt 1. Jul 2015, 18:01
Hello

Da hast du ja einen ganz schönen Brocken bekommen ...

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?
Ich vermute, dass frmSpeicherverzeichnis entweder eine globale Variable oder ein Property von TfrmSplash 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 Speicherverzeichnis schon gesetzt wurde.

Weiterhin sieht es so aus, als ob er hier ein ShowModal "simuliert". Das lässt der darunterliegende Block vermuten:
Delphi-Quellcode:
while assigned(frmSpeicherverzeichnis) do
  begin
    Application.ProcessMessages;
  end;
Das ist sehr unsauber, da es den gesamten restlichen Programmablauf in der Schleife blockiert.

Warum er hier nicht einfach ...
Delphi-Quellcode:
if Speicherverzeichnis='then
  begin
    frmSpeicherverzeichnis := TfrmSpeicherverzeichnis.Create(Self);
    frmSpeicherverzeichnis.ShowModal;
  end;
... verwendet, kann ich aus dem Code jedoch nicht ersehen.

Warum das "self.hide" seiner Startoberfläche? Da sind keine Elemente/ Objekte, die er nochmal benutzt.
Ich vermute, dass er hier das Elternformular (frmSplash ) verstecken will?

Genauso auch hier:
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;
Statt ...
Delphi-Quellcode:
Application.CreateForm(TfrmOptionen, frmOptionen);
frmOptionen.show;
self.Enabled:=False;
... kann man (theoretisch) auch ...
Delphi-Quellcode:
frmOptionen := TfrmOptionen.Create(Self);
frmOptionen.ShowModal;
... machen.

Ich habe im Forum so viel rausbekommen, dass ...
Form.close = Form.Visible := false
Jein, nicht ganz. Form.Close prüft über Form.CloseQuery , ob eine Form geschlossen werden kann. Wenn Form.CloseQuery CanClose := FALSE setzt, bleibt die Form offen.

Form.release = setzt eine Application. Message ab/ gibt aber nix frei
Richtig. Form.Release setzt eine Message in die MessageQueue, die "irgendwann" verarbeitet wird und erst dann wird das Fenster geschlossen.
Ich habe aber auch mal gelernt, dass man nicht mit Release arbeiten sollte.

Form.Free ist was anderes als Form.freeAndNil
Gibt es Form.FreeAndNil in Delphi 5 wirklich (noch)? Ich habe das jedenfalls hier nicht. Es gibt die Funktion FreeAndNil(var ObjectReference) , die eine übergebene Variable des Typs TObject nach dem Freigeben auf nil setzt. FreeAndNil macht also nichts anderes als ObjectReference.Free; ObjectReference := nil
Ist es wirklich sinnvol, die aufrufende Form immer Enabled:=false zu setzen?
Ohne den Rest zu kennen: Nein, sinnvoller wäre es, mit ShowModal zu arbeiten. Es sei denn es gibt zwingend Gründe, warum man das so machen müsste.

Auf manchen Seiten steht bei CloseQuery nur CanClose:=false und beim Abbrechen-Button aber nur close; !? da kann ich doch das CloseQuery weglassen oder?
Ich vermute, dadurch, dass der ursprüngliche Programmierer hier mit Release arbeit, er das CloseQuery "ü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.

Mir wiederstrebt es irgendwie die Form nicht in sich selbst zu beenden (Form.CloseQuery)... ist das nicht sauberer
Wie schon gesagt: Wir kennen den Rest nicht und wissen auch nicht, was der Programmierer sich dabei gedacht hat. Aber ja, prinzipiell wäre es "sauberer", eine nicht mehr benötigte Form an der Stelle zu schliessen / freizugeben, wo sie ihren Zweck erfüllt hat.

reicht es nicht (so hab ich es bisher gemacht ... bin kein Programmierer):
Delphi-Quellcode:
procedure TfrmMomentanwerte.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
     frmMomentanwerte.Release;
     frmMomentanwerte := nil;
end;
CloseQuery sollte nur am Ende CanClose setzen. Sonst nichts anderes.

Wenn es eine globale Variable frmMomentanwerte gibt, die unbedingt auf nil gesetzt werden muss, dann sollte das entweder in OnClose oder OnDestroy passieren.

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 ShowModal benutzt.

Geändert von nuclearping ( 1. Jul 2015 um 18:05 Uhr)
  Mit Zitat antworten Zitat
die Suchende

Registriert seit: 27. Mär 2009
16 Beiträge
 
#3

AW: dynamisch erzeugte Forms richtig freigeben

  Alt 2. Jul 2015, 09:41
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:
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;
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.

Grüße
die Suchende
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.624 Beiträge
 
Delphi 12 Athens
 
#4

AW: dynamisch erzeugte Forms richtig freigeben

  Alt 2. Jul 2015, 09:50
Wenn Du dynamische modale Fenster brauchst, geht das eigentlich ganz einfach.
Delphi-Quellcode:
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;
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.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
die Suchende

Registriert seit: 27. Mär 2009
16 Beiträge
 
#5

AW: dynamisch erzeugte Forms richtig freigeben

  Alt 2. Jul 2015, 10:13
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.
  Mit Zitat antworten Zitat
Perlsau
(Gast)

n/a Beiträge
 
#6

AW: dynamisch erzeugte Forms richtig freigeben

  Alt 2. Jul 2015, 10:22
... 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." ...
.
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 Modalresult ungleich mrNone das modale Fenster geschlossen wird.
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
642 Beiträge
 
Delphi 10.1 Berlin Professional
 
#7

AW: dynamisch erzeugte Forms richtig freigeben

  Alt 2. Jul 2015, 14:09
... 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....
Da hat er prinzipiell auch recht. Aber, wenn man das Schließen eines Fensters sowieso nur über entsprechende Buttons ermöglichen will, wozu dann überhaupt das [X] anzeigen? Das ist meiner Meinung nach unsinnig.

Also weg mit allen BorderIcons und Alt+F4 abfangen, und gut isses. Dann wird auch sauberer Code daraus.
Gruss Otto PS: Sorry wenn ich manchmal banale Fragen stelle. Ich bin Hobby-Programmierer und nicht zu faul die SuFu zu benutzen
  Mit Zitat antworten Zitat
BadenPower

Registriert seit: 17. Jun 2009
616 Beiträge
 
#8

AW: dynamisch erzeugte Forms richtig freigeben

  Alt 2. Jul 2015, 15:19
Aber, wenn man das Schließen eines Fensters sowieso nur über entsprechende Buttons ermöglichen will, wozu dann überhaupt das [X] anzeigen? Das ist meiner Meinung nach unsinnig.

Also weg mit allen BorderIcons und Alt+F4 abfangen, und gut isses. Dann wird auch sauberer Code daraus.
Einfach das [X] deaktivieren, dann kannst Du die restlichen BorderIcons und das Systemmenu immer noch benutzen und brauchst noch nicht einmal Alt+F4 abfangen.
Programmieren ist die Kunst aus Nullen und Einsen etwas sinnvollen zu gestalten.
Der bessere Künstler ist allerdings der Anwender, denn dieser findet Fehler, welche sich der Programmierer nicht vorstellen konnte.
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.624 Beiträge
 
Delphi 12 Athens
 
#9

AW: dynamisch erzeugte Forms richtig freigeben

  Alt 2. Jul 2015, 15:57
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?
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von baumina
baumina

Registriert seit: 5. Mai 2008
Ort: Oberschwaben
1.275 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: dynamisch erzeugte Forms richtig freigeben

  Alt 2. Jul 2015, 16:12
Wird das Fenster einfach geschlossen, ist ModalResult mrNone
Wird ein modales Fenster mit X oder Alt-F4 geschlossen, ist Modalresult = mrCancel, nicht mrNone.
Hinter dir gehts abwärts und vor dir steil bergauf ! (Wolfgang Ambros)
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:34 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