AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Mehrere Formulare schließen (mit Sicherheitsfrage)
Thema durchsuchen
Ansicht
Themen-Optionen

Mehrere Formulare schließen (mit Sicherheitsfrage)

Ein Thema von ndy · begonnen am 18. Mär 2015 · letzter Beitrag vom 19. Mär 2015
Antwort Antwort
Seite 1 von 2  1 2      
ndy

Registriert seit: 18. Mär 2015
Ort: Dresden
8 Beiträge
 
Delphi XE2 Professional
 
#1

Mehrere Formulare schließen (mit Sicherheitsfrage)

  Alt 18. Mär 2015, 17:19
Hallo,

folgendes wird wohl eher eine Verständnisfrage für mich persönlich. Eventuell ist sie sogar so trivial, dass ich hier gleich gesteinigt werde.

Ich bin ein Laie in Sachen Delphi-Programmierung und soll gerade mit Delphi XE2 ein bestehendes Programm "erweitern". Aus Gründen der Übersicht habe ich dazu eine neue Form erstellt (die Hauptform ist mit Labels, Edits und Images für meinen Geschmack schon ziemlich überladen). Das Programm soll auf beiden Formularen sicher beendet werden können. Im Hauptformular (das bereits existierte) wird das wohl so realisiert:

Delphi-Quellcode:
Function TFrm_Form1.Beenden():Boolean;
begin
  if Application.MessageBox('Wirklich beenden?','Berechnung',52) = 6 then
 begin
 ...
 Application.Terminate;
 result:=True;
 end else result:=false;
end; //TFrm_Form1.Beenden

...

procedure TFrm_Form1.Beenden1Click(Sender: TObject);
begin
  Beenden;
end;

...

procedure TFrm_Form1.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
CanClose:=Beenden;
end;
Mit der Prozedur "Beenden1Click" wird das Beenden mittels Button abgearbeitet. Ich gehe davon aus, dass Beenden mittels Rechtsklick in der Symbolleiste, Alt+F4, [X]-Button etc. über die FormCloseQuery-Prozedur abgearbeitet wird.

Nun gleich zu einer ersten Zwischenfrage zum persönlichen Verständnis:
(1) Wofür stehen die Konstanten bei Application.Messagebox? (52 und 6)
Hab auf die schnelle nur diese Übersicht gefunden. Die ist wohl aber etwas veraltet, da ich die Konstanten unter MessageBox nicht wiedergefunden habe.
Ich tippe jetzt einfach mal auf 52 = /!\ und 6 = MB_OK

Weiter im Text: Den Wechsel zwischen den Formularen realisiere ich wie folgt:

Delphi-Quellcode:
procedure TFrm_Form1.B_WechselZuForm2Click(Sender: TObject);
begin
  Frm_Form2.Top := Frm_Form1.Top;
  Frm_Form2.Left := Frm_Form1.Left;
  Frm_Form2.Height := Frm_Form1.Height;
  Frm_Form2.Width := Frm_Form1.Width;
  Frm_Form2.Show;
  Frm_Form1.Hide;
end;
Der Wechsel von Form2 zu Form1 ist analog aufgebaut.

Jetzt zum eigentlichen Problem: Das schließen dieser zweiten Form. Anfangs habe ich gedacht es würde reichen, wenn ich auf die Beenden-Prozedur von Form1 verweise, also quasi:

Delphi-Quellcode:
//////////Beenden via "Beenden"-Button
procedure TFrm_Form2.B_Form2BeendenClick(Sender: TObject);
begin
  Frm_Form1.Beenden;
end;

...

procedure TFrm_Form2.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
CanClose:=Frm_Form1.Beenden;
end;
Das würde für das Beenden über den entsprechenden Button auch funktionieren. Allerdings wird damit nicht das Beenden via Rechtsklick, Alt+F4, [X]-Button usw. abgefangen. Vermutlich wird das FormCloseQuery garnicht angelaufen (habe ich mittels Breakpoints untersucht). Hab gelesen, dass das wohl nur bei modalem Aufruf ginge oder so. Da ich die Formulare aber nicht schließen möchte wenn ich das jeweils andere Formular anzeigen will (in die Edits eingetragene/geänderte Werte sollen nicht verloren gehen), was ich wohl müsste wenn ich mit ShowModal arbeite, hab ich den Formularwechsel via Show und Hide realisiert (siehe oben).
Auch eine eigene Funktion Beenden für Form2 (im Prinzip exakt die gleiche wie für Form1) hat das Problem nicht behoben.

Im Internet bin ich dann auf diese Möglichkeit gestoßen so ziemlich alle Varianten des Programm beendens (außer via Button) abzufangen. Der Rohquelltext sieht so aus:

Delphi-Quellcode:
procedure WMSysCommand(var MSG: TWMSysCommand); message WM_SYSCOMMAND;

...

procedure TForm1.WMSYSCommand(var MSG: TWMSysCommand);
begin
  if MSG.CmdType = SC_CLOSE then
  begin
     //Closing from border icon
  end;
  inherited;
end;
Nun habe ich mir Gedanken gemacht, wie ich da noch die Abfrage (Wirklich Beenden?) dazwischenbekomme und auf ein Nein als Antwort reagiere. Dabei bin ich auf folgende Lösungen gestoßen:

Delphi-Quellcode:
Function TFrm_Form2.Beenden():Boolean;
begin
  if Application.MessageBox('Wirklich beenden?','Berechnung',52) = 6 then
 begin
...
 Application.Terminate;
 result:=True;
 end else result:=false;
end;

...

procedure TFrm_Form2.WMSysCommand(var MSG: TWMSysCommand);
begin
  if MSG.CmdType = SC_CLOSE then
  begin
    if Frm_Form2.Beenden = False then
    begin
      MSG.Result := 0;
      Exit;
    // MSG.CmdType := SC_DEFAULT;
    end;
  end;
  inherited;
end;
Das letzte Stück Quelltext durchschaue ich noch nicht ganz, darum jetzt zur eigentlichen Thematik:
Als mögliche Werte für Msg:CmdType bin ich unter anderem auf SC_DEFAULT gestoßen (leider keine Ahnung mehr wo). Das war auch mein erster Lösungsansatz (siehe auskommentierte Zeile), der auch (scheinbar?) funktioniert hat. Jedoch bin ich mir nicht sicher, ob man MSG.CmdType einfach so einen neuen Wert zuweisen kann/sollte und ob SC_DEFAULT nicht vielleicht auch irgendwas anderes "auslöscht".
Die zweite Möglichkeit
(
MSG.Result := 0;
Exit;
)
habe ich zu einer anderen Thematik gefunden (irgendwas von wegen Maximieren, Minimieren verhindern oder so).
Nach ein wenig rumprobieren habe ich gemerkt, dass Exit allein auch funktioniert.

Nun (endlich ) zu meinen Hauptfragen:

(2) Möglichkeit 1: Richte ich mit der Zuweisung von SC_DEFAULT ungewollt und unbewussten Schaden an? Oder anders gefragt: Würde das so funktionieren?

(3) Möglichkeit 2: Wenn Exit allein funktioniert, wozu dann MSG.Result := 0;? Und was bedeutet das?


Vielen Dank im Voraus!


PS: Wie eingangs erwähnt bin ich ein absoluter Laie auf dem Gebiet Delphi-Programmierung (eigentlich auch allgemein auf dem Gebiet der Programmierung). Die einzigen Kenntnisse die ich habe liegen schon ein paar Jährchen zurück und waren recht simpel gehalten (ein oder ein halbes Jahr Informatikunterricht). Deshalb hab ich für mich persönlich bei der Fragestellung einfach beim Urschleim angefangen. Zum einen in der Hoffnung auf grobe Fehler hingewiesen zu werden und zum anderen um Fragen so gut es geht vorzubeugen.
Bei Fehlern bei der Fragestellung und Themeneröffnung bitte ich mich darauf hinzuweisen und sie mir nachzusehen

Geändert von ndy (18. Mär 2015 um 17:25 Uhr) Grund: Quelltext ergänzt
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.160 Beiträge
 
Delphi 10 Seattle Enterprise
 
#2

AW: Mehrere Formulare schließen (mit Sicherheitsfrage)

  Alt 18. Mär 2015, 17:38
Hallo und Willkommen in den Heiligen Hallen des Wissens und des Wahnsinns.

(1) Wofür stehen die Konstanten bei Application.Messagebox? (52 und 6)
Hab auf die schnelle nur diese Übersicht gefunden. Die ist wohl aber etwas veraltet
Die "magischen Nummern" wie 52 und 6 sind ein absolutes Verbrechen das dich jetzt schon viel unnötige Zeit gekostet hat! Das einzige was dir hier vielleicht noch helfen kann ist die Dokumentation zu den Befehlen: Die Hilfe versteckt sich hinter der F1-Taste und kann hier wirklich weiterhelfen:
Zu TApplication.MessageBox(..) findest du die Werte die sich als dritter Parameter ("Flags") angeben lassen und was man zurückbekommt: Es sind Konstanten aus der Unit "WinApi.Windows".

Die "52" steht für "Schaltfläche ja+nein und bitte ein Ausrufezeiche-Icon". Kann man das aus einer "52" herauslesen? Nein. Deshalb sollte man lieber die vorgefertigten Werte "MB_YESNO" und "MB_ICONEXCLAMATION" dafür verwenden.

Vernünftig geschrieben sähe die Zeile also so aus:
if Application.MessageBox('Wirklich beenden?', 'Berechnung', MB_YESNO or MB_ICONEXCLAMATION) = IDYES then [...] oder noch besser:
Delphi-Quellcode:
const
   flags: DWORD = MB_YESNO or MB_ICONEXCLAMATION;
begin
   if Application.MessageBox('Wirklich beenden?', 'Berechnung', flags) = IDYES then [...]

Auch: Die offizielle Doku ist nicht perfekt, aber besser als sie auf den ersten Blick scheint. Grade bei Delphi sind die meisten Internet-Treffer die du finden wirst gerne 10-15 Jahre alt. Ich würde mich davor hüten.

Zu den weiteren Punkten bekommst du mit Sicherheit noch mehr Input

Geändert von Der schöne Günther (18. Mär 2015 um 17:42 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#3

AW: Mehrere Formulare schließen (mit Sicherheitsfrage)

  Alt 18. Mär 2015, 18:53
von mir leider keine Antwort zu den eigentlichen Fragen sondern
Bitte nie so etwas
if Frm_Form2.Beenden = False then nutzen, sondern immer
if not(Frm_Form2.Beenden) then Ich vermute eine Modifizierung ist keine so gute Idee.

Gruß
K-H
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
BadenPower

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

AW: Mehrere Formulare schließen (mit Sicherheitsfrage)

  Alt 18. Mär 2015, 20:39
Bitte nie so etwas
if Frm_Form2.Beenden = False then nutzen, sondern immer
if not(Frm_Form2.Beenden) then
Weshalb?
Da sehe ich keinen Sinn, warum man nicht auch Variante 1 benutzen soll, wenn man dies bevorzugt.
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 Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Mehrere Formulare schließen (mit Sicherheitsfrage)

  Alt 18. Mär 2015, 21:35
Bitte nie so etwas
if Frm_Form2.Beenden = False then nutzen, sondern immer
if not(Frm_Form2.Beenden) then
Weshalb?
Da sehe ich keinen Sinn, warum man nicht auch Variante 1 benutzen soll, wenn man dies bevorzugt.
Mal abgesehen davon das die Benutzung der globalen Form-Variablen in der Form-Klasse ein klassisches Eigentor werden kann und somit statt Frn_Form2.Beenden immer Self.Beenden oder schlicht und ergreifend Beenden benutzt werden sollte, ist gegen das Verwenden von if Self.Beenden = False then erst mal nichts einzuwenden.

Doof ist nur, dass diese Leute, die sich das angewöhnen eben dann an anderer Stelle analog auch if Self.Beenden = True then schreiben. Und dort liegen dann wieder potentielle Fehlerquellen (ist in diesem Forum schon bis zum Erbrechen durchgekaut worden und bei Interesse bitte die Forensuche benutzen und bitte hier nicht wieder aufwärmen).

Generell würde ich die Methode sogar umbenennen um zu verdeutlichen, dass hier in der Funktion noch eine Entscheidung getroffen wird:
Delphi-Quellcode:
if not Self.ShouldClose
then
  ...
// oder anders herum
if Self.ShouldClose
then
  ...
Schon liest sich das wie Prosa ... und darum geht es bei der Programmierung auch: Robuster und selbsterklärender Code
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (18. Mär 2015 um 21:38 Uhr)
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#6

AW: Mehrere Formulare schließen (mit Sicherheitsfrage)

  Alt 19. Mär 2015, 05:00
...ist gegen das Verwenden von if Self.Beenden = False then erst mal nichts einzuwenden.
Doch: Schlechter lesbar, da keine Prosa. Es heißt doch 'Wenn ich nicht beenden will' und nicht 'Wenn 'Beenden' falsch ist'.
  Mit Zitat antworten Zitat
bcvs

Registriert seit: 16. Jun 2011
703 Beiträge
 
Delphi 12 Athens
 
#7

AW: Mehrere Formulare schließen (mit Sicherheitsfrage)

  Alt 19. Mär 2015, 07:58
Aus Gründen der Übersicht habe ich dazu eine neue Form erstellt (die Hauptform ist mit Labels, Edits und Images für meinen Geschmack schon ziemlich überladen). Das Programm soll auf beiden Formularen sicher beendet werden können.
Du willst also eine mit Controls überladene Form für den Benutzer entzerren. Das ist schon mal ein guter Gedanke.
Ich würde das allerdings nicht über eine zweite Form lösen, die dann eifach über die erste Form drübergeblendet wird. Pack die Controls auf verschiedene Seiten eines TPageControl. Wenn du willst, kann man die Tab-Reiter mit TabVisible:=false unsichtbar machen. Umschalten zwischen den Tabs erfolgt dann mit PageControl.ActivePage:=... Du hast dann aber programmtechnisch immer noch ein Form, das ganz normal beendet werden kann, sparst dir das Gehampele mit WMSysCommand und die Circular Unit Reference, dass Form1 Form2 kennen muss und umgekehrt.
  Mit Zitat antworten Zitat
ndy

Registriert seit: 18. Mär 2015
Ort: Dresden
8 Beiträge
 
Delphi XE2 Professional
 
#8

AW: Mehrere Formulare schließen (mit Sicherheitsfrage)

  Alt 19. Mär 2015, 10:07
Die "52" steht für "Schaltfläche ja+nein und bitte ein Ausrufezeiche-Icon". Kann man das aus einer "52" herauslesen? Nein. Deshalb sollte man lieber die vorgefertigten Werte "MB_YESNO" und "MB_ICONEXCLAMATION" dafür verwenden.
Vielen Dank!

Sieht auf den ersten Blick wirklich etwas besser aus. Außerdem braucht es nicht viel Fantasie um zu erahnen, dass eine Internetsuche nach "MB_YESNO", "MB_ICONEXCLAMATION" bzw. "MB_OK" vermutlich erfolgreicher / effizienter wäre als nach "52" und "6", womit sich das Problem wohl von selbst gelöst hätte.

Bitte nie so etwas
if Frm_Form2.Beenden = False then nutzen, sondern immer
if not(Frm_Form2.Beenden) then Ich vermute eine Modifizierung ist keine so gute Idee.
statt Frn_Form2.Beenden immer Self.Beenden
Alles klar, danke

Ich vermute if Frm_Form2.Beenden = False then läuft unter der Rubrik "von hinten durch die Brust und durchs Auge ins Herz", also unnötig kompliziert. Liest sich jetzt verständlicher. Wobei das mit "self" im allerersten Moment etwas ungewohnt war. Klingt aber auch sinnvoll.


Ich würde das allerdings nicht über eine zweite Form lösen, die dann eifach über die erste Form drübergeblendet wird. Pack die Controls auf verschiedene Seiten eines TPageControl. Wenn du willst, kann man die Tab-Reiter mit TabVisible:=false unsichtbar machen. Umschalten zwischen den Tabs erfolgt dann mit PageControl.ActivePage:=... Du hast dann aber programmtechnisch immer noch ein Form, das ganz normal beendet werden kann, sparst dir das Gehampele mit WMSysCommand und die Circular Unit Reference, dass Form1 Form2 kennen muss und umgekehrt.
Danke, das ist natürlich auch eine Möglichkeit die ich erstmal komplett nicht auf dem Schirm hatte. Allerdings funktioniert es ja grundsätzlich erstmal so, wie ich es realisiert habe. Mich würde nur interessieren, was da genau dahinter steckt
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: Mehrere Formulare schließen (mit Sicherheitsfrage)

  Alt 19. Mär 2015, 10:46
statt Frn_Form2.Beenden immer Self.Beenden
Wobei das mit "self" im allerersten Moment etwas ungewohnt war. Klingt aber auch sinnvoll.
Es wird doch immer das ausgeführt, was man schreibt und nicht das was man sich beim Schreiben gedacht hat (die MindRead-API ist noch lange nicht fertig).

So und was hat man geschrieben, wenn man das hier schreibt:
Delphi-Quellcode:
TFoo = class
  procedure Bar();
  procedure FooBar();
end;

var
  Foo : TFoo;

procedure TFoo.Bar;
begin
  Foo.FooBar();
end;

procedure TFoo.FooBar;
begin
end;
Man hat geschrieben, dass beim Aufruf der Methode TFoo.Bar die Methode TFoo.FooBar im Kontext der Instanz ausgeführt werden soll, deren Referenz in der Variablen Foo hinterlegt ist.

Und jetzt:
Delphi-Quellcode:
procedure TFoo.Bar;
begin
  {Self.}FooBar();
end;
Man hat geschrieben, dass beim Aufruf der Methode TFoo.Bar die Methode TFoo.FooBar im eigenen (Self ) Instanz-Kontext ausgeführt werden soll.

Gibt es nur eine Instanz von der Klasse und wird die Referenz auf diese Instanz auch zuverlässig in der Variablen Foo: TFoo gespeichert, dann funktionieren beide Ansätze.

Gibt es mehr als eine Instanz, dann habe ich die Torte im Auge.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
BadenPower

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

AW: Mehrere Formulare schließen (mit Sicherheitsfrage)

  Alt 19. Mär 2015, 11:02
Doof ist nur, dass diese Leute, die sich das angewöhnen eben dann an anderer Stelle analog auch if Self.Beenden = True then schreiben. Und dort liegen dann wieder potentielle Fehlerquellen (ist in diesem Forum schon bis zum Erbrechen durchgekaut worden und bei Interesse bitte die Forensuche benutzen und bitte hier nicht wieder aufwärmen).
Ich wollte hier ja keine Grundsatzdebatte auslösen, sondern lediglich darlegen, dass es grundsätzlich ersteinmal nicht falsch ist, das so zu machen.

Dass die Prüfung auf "true" eine Fehlerquelle sein kann, wenn man nicht weis was man da prüft, ist auch richtig.

Aber es kann auch vorkommen, dass man bewußt auf die Konstante "True" if (RückgabeWert() = true) then oder "False" if (RückgabeWert() = false) then prüfen MUSS, damit man das richtige Ergebnis erhält und nicht auf irgendetwas was Wahr if (RückgabeWert()) then oder Falsch if not (RückgabeWert()) then ERGIBT.

Und dies wird meist in den ganzen Diskussionen vergessen zu erwähnen.
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
Antwort Antwort
Seite 1 von 2  1 2      

 

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 23:22 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