![]() |
Mehrere Formulare schließen (mit Sicherheitsfrage)
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:
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.
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; 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 ![]() 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:
Der Wechsel von Form2 zu Form1 ist analog aufgebaut.
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; 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:
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).
//////////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; 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 ![]()
Delphi-Quellcode:
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:
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;
Delphi-Quellcode:
Das letzte Stück Quelltext durchschaue ich noch nicht ganz, darum jetzt zur eigentlichen Thematik:
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; 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 :D) 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 :wink: 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 :wink: |
AW: Mehrere Formulare schließen (mit Sicherheitsfrage)
Hallo und Willkommen in den Heiligen Hallen des Wissens und des Wahnsinns. :drunken:
Zitat:
Zu ![]() 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:
Delphi-Quellcode:
oder noch besser:
if Application.MessageBox('Wirklich beenden?', 'Berechnung', MB_YESNO or MB_ICONEXCLAMATION) = IDYES then [...]
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 |
AW: Mehrere Formulare schließen (mit Sicherheitsfrage)
von mir leider keine Antwort zu den eigentlichen Fragen sondern
Bitte nie so etwas
Delphi-Quellcode:
nutzen, sondern immer
if Frm_Form2.Beenden = False then
Delphi-Quellcode:
Ich vermute eine Modifizierung ist keine so gute Idee.
if not(Frm_Form2.Beenden) then
Gruß K-H |
AW: Mehrere Formulare schließen (mit Sicherheitsfrage)
Zitat:
Da sehe ich keinen Sinn, warum man nicht auch Variante 1 benutzen soll, wenn man dies bevorzugt. |
AW: Mehrere Formulare schließen (mit Sicherheitsfrage)
Zitat:
Delphi-Quellcode:
immer
Frn_Form2.Beenden
Delphi-Quellcode:
oder schlicht und ergreifend
Self.Beenden
Delphi-Quellcode:
benutzt werden sollte, ist gegen das Verwenden von
Beenden
Delphi-Quellcode:
erst mal nichts einzuwenden.
if Self.Beenden = False then
Doof ist nur, dass diese Leute, die sich das angewöhnen eben dann an anderer Stelle analog auch
Delphi-Quellcode:
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).
if Self.Beenden = True then
Generell würde ich die Methode sogar umbenennen um zu verdeutlichen, dass hier in der Funktion noch eine Entscheidung getroffen wird:
Delphi-Quellcode:
Schon liest sich das wie Prosa ... und darum geht es bei der Programmierung auch: Robuster und selbsterklärender Code
if not Self.ShouldClose
then ... // oder anders herum if Self.ShouldClose then ... |
AW: Mehrere Formulare schließen (mit Sicherheitsfrage)
Zitat:
|
AW: Mehrere Formulare schließen (mit Sicherheitsfrage)
Zitat:
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
Delphi-Quellcode:
unsichtbar machen. Umschalten zwischen den Tabs erfolgt dann mit
TabVisible:=false
Delphi-Quellcode:
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.
PageControl.ActivePage:=...
|
AW: Mehrere Formulare schließen (mit Sicherheitsfrage)
Zitat:
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. Zitat:
Zitat:
Ich vermute
Delphi-Quellcode:
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.
if Frm_Form2.Beenden = False then
Zitat:
|
AW: Mehrere Formulare schließen (mit Sicherheitsfrage)
Zitat:
So und was hat man geschrieben, wenn man das hier schreibt:
Delphi-Quellcode:
Man hat geschrieben, dass beim Aufruf der Methode
TFoo = class
procedure Bar(); procedure FooBar(); end; var Foo : TFoo; procedure TFoo.Bar; begin Foo.FooBar(); end; procedure TFoo.FooBar; begin end;
Delphi-Quellcode:
die Methode
TFoo.Bar
Delphi-Quellcode:
im Kontext der Instanz ausgeführt werden soll, deren Referenz in der Variablen
TFoo.FooBar
Delphi-Quellcode:
hinterlegt ist.
Foo
Und jetzt:
Delphi-Quellcode:
Man hat geschrieben, dass beim Aufruf der Methode
procedure TFoo.Bar;
begin {Self.}FooBar(); end;
Delphi-Quellcode:
die Methode
TFoo.Bar
Delphi-Quellcode:
im eigenen (
TFoo.FooBar
Delphi-Quellcode:
) Instanz-Kontext ausgeführt werden soll.
Self
Gibt es nur eine Instanz von der Klasse und wird die Referenz auf diese Instanz auch zuverlässig in der Variablen
Delphi-Quellcode:
gespeichert, dann funktionieren beide Ansätze.
Foo: TFoo
Gibt es mehr als eine Instanz, dann habe ich die Torte im Auge. |
AW: Mehrere Formulare schließen (mit Sicherheitsfrage)
Zitat:
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"
Delphi-Quellcode:
oder "False"
if (RückgabeWert() = true) then
Delphi-Quellcode:
prüfen MUSS, damit man das richtige Ergebnis erhält und nicht auf irgendetwas was Wahr
if (RückgabeWert() = false) then
Delphi-Quellcode:
oder Falsch
if (RückgabeWert()) then
Delphi-Quellcode:
ERGIBT.
if not (RückgabeWert()) then
Und dies wird meist in den ganzen Diskussionen vergessen zu erwähnen. |
AW: Mehrere Formulare schließen (mit Sicherheitsfrage)
Zitat:
Zitat:
Zitat:
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:54 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