![]() |
Fenster schließt sich nicht
Hallo,
in einer D11.3 VCL Anwendung habe ich ein neues Fenster hinzugefügt. Dieses wird mit ShowModal aufgerufen und hat ein Ereignis, das ich vorher zuweise welches von diesem Formular im OnShow aufgerufen wird. Dieses Ereignis Startet eine Aktion welche über ein Event eine Methode dieses Fensters aufruft um den Status der Operation anzuzeigen. Dise Methode hat u.a. einen Cound und einen Index Parameter. Sind beide gleich ist die Operation zuende und das Fenster soll geschlossen werden. Ich rufe daher Close bzw. inzwschen self.Close auf, aber es schließt sich nicht automatisch. Auch der OK Button im Fenster wird enabled (ja, im Gutfall etwas schwachsinnig, der OK Button ist eigentlich für den Fehlerfall, da soll der Dilog sich nicht automatisch schließen. Klicke ich auf OK im Fenster wird es geschlossen. Das Fenster hat keine Eventhandler für OnClose oder OnCloseQuery. Hat jemand eine Idee was ein Schließen eines Fensters mittels Close verhindern kann? Grüße TurboMagic |
AW: Fenster schließt sich nicht
Setz einfach ModalResult := mrOK; bei modalen Fenstern funktioniert Close nicht ganz so wie bei nicht-modalen.
|
AW: Fenster schließt sich nicht
Close funktioniert bei Modalen, und auch teilweise bei Nicht-Modalen.
[edit] siehe #7 und #6 Bei Modalem macht es einfach nur
Delphi-Quellcode:
, also funktional kein Unterschied zu deinem Lösungsvorschlag.
ModalResult := mrCancel;
OnClose und OnyCloseQuery wird bei Dialogen (modalen Forms) aber sowieso niemals aufgerufen. (ja, das ist IMHO ein Bug, aber der ist schon seit 20 Jahren so, also weigert sich wer das zu reparieren) Natürlich schließt Close beim Modaten das Fenster niemals sofort, sondern erst wenn ShowModal verlassen wird, also nichts die MessageLoop darin blockiert (z.B. ein Sleep oder eine Schleife im Event). Free würde es sofort schließen, daber das benutzt man hier NIEMALS, denn wenn doch, dann knallt es anschließend. |
AW: Fenster schließt sich nicht
Danke für die Tipps, werde ich baldmöglichst mal ausprobieren...
|
AW: Fenster schließt sich nicht
Zitat:
|
AW: Fenster schließt sich nicht
Zitat:
Delphi-Quellcode:
Sollte das bei dir nicht funktionieren, dann liegt das vermutlich nicht an Delphi. Vielleicht stimmt auch was mit deinem TestCase nicht.
procedure TCustomForm.CloseModal;
var CloseAction: TCloseAction; begin try CloseAction := caNone; if CloseQuery then begin CloseAction := caHide; DoClose(CloseAction); end; case CloseAction of caNone: ModalResult := 0; caFree: Release; end; except ModalResult := 0; Application.HandleException(Self); end; end; |
AW: Fenster schließt sich nicht
OK, hab nur nach Close geguckt.
Seh ich es richtig, oder verändert dieses Mistteil von CloseModal bösartig das ModalResult? Von mrCancel zu mrNone, worauf dann wirklich die Form nicht mehr geschlossen wird. :wall: Wer denkt sich soeinen Scheißdreck aus? ![]()
Delphi-Quellcode:
procedure TCustomForm.Close;
var CloseAction: TCloseAction; begin if fsModal in FFormState then ModalResult := mrCancel <<<<<<<<<<< else if CloseQuery then begin if FormStyle = fsMDIChild then if biMinimize in BorderIcons then CloseAction := caMinimize else CloseAction := caNone else CloseAction := caHide; DoClose(CloseAction); if CloseAction <> caNone then if Application.MainForm = Self then Application.Terminate else if CloseAction = caHide then Hide else if CloseAction = caMinimize then WindowState := wsMinimized else Release; end; end;
Delphi-Quellcode:
Echt mal, warum kann man nicht an der Stelle einen Kommentar rein tun?
function TCustomForm.ShowModal: Integer;
begin ... ModalResult := 0; repeat ... Application.HandleMessage; if Application.Terminated then ModalResult := mrCancel else if ModalResult <> 0 then CloseModal; until ModalResult <> 0; Also dass Teile aus dem Else "hier" oben auch gemacht werden, nur nicht hier, sondern erst später in ShowModal->CloseModal, vorm Ende der Schleife. (außer wenn Terminated) Das protected CloseModal (mich wundert echt, dass es nicht private ist) wird/sollte man sowieso nicht selber aufrufen. Es bleibt beim Close. |
AW: Fenster schließt sich nicht
Das Setzen von Modalresult im OnShow oder OnActivate Event ist leider zu früh, da im Showmodal erst danach die Schleife beginnt, diedie Abbruchbedingung enthält.
Hier nur ein Auszug:
Delphi-Quellcode:
Wenn man die Form im OnShow oder OnAvtivate schließen möchte, dann per
try
Show; try SendMessage(Handle, CM_ACTIVATE, 0, 0); ModalResult := 0; repeat ... ... until ModalResult <> 0;
Delphi-Quellcode:
PostMessage(FormHandle, WM_CLOSE, 0, 0);
Vielleicht wäre es besser im OnShow einen Thread zu starten, der die Methode ausführt und über Synchronice die Anzeige zu aktualisieren und im OnTerminate das Form zu schließen. |
AW: Fenster schließt sich nicht
Zitat:
|
AW: Fenster schließt sich nicht
uppps, falsch geguckt .... war caNone, nicht mrNone ... und davor den Variablennamen nicht nochmal gelesen :wall:
Delphi-Quellcode:
procedure TCustomForm.Close;
var CloseAction: TCloseAction; begin if fsModal in FFormState then ModalResult := mrCancel else function TCustomForm.ShowModal: Integer; begin ... ModalResult := 0; repeat ... Application.HandleMessage; <<<<<<<<<<<<<<< hier würde das .Close ausgeführt oder ein ModalResult gesetzt if Application.Terminated then ModalResult := mrCancel else if ModalResult <> 0 then CloseModal; until ModalResult <> 0; procedure TCustomForm.CloseModal; var CloseAction: TCloseAction; begin try CloseAction := caNone; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< if CloseQuery then |
AW: Fenster schließt sich nicht
Ich würde sagen du darfst dein "Ereignis" nicht in OnShow aufrufen.
Ich habe früher für sowas in der Regel einen TTimer verwendet der in OnShow aktiviert wird und dann, wenn die MessageQueue bock hat aufgerufen wird und sich selbst direkt disabled und die Aktion die ich möchte "direkt nach dem Aufbau des fensters" ausführt. "PostMessage" macht aber ansich das Gleiche und legt auch einfach eine Message auf die Queue die dann, wenn alle anderen Messages(paint, focus, MouseUp) durch sind abgearbeitet werden. |
AW: Fenster schließt sich nicht
Statt PostMessage und Timer verwende ich hier gern das Thread.Queue
Delphi-Quellcode:
ACHTUNG: ForceQueue statt Queue, da Emba zu dämlich war Queue zu reparieren und den "Bugfix" anders nannte. (im VCL-Thread aufgerufen, führt TThread.Queue den Code sofort aus ... anstatt dieses falsche IF einfach zu löschen, wurde eine neue Funktion gebaut, die endlich das macht, was die Funkion "Queue" laut ihrem Namen beheuptet zu tun)
TThread.ForceQueue(nil, procedure // im OnShow oder OnCreate/Create
begin ... end); |
AW: Fenster schließt sich nicht
Zitat:
|
AW: Fenster schließt sich nicht
Man könnte aber auch einfach immer und überall ForceQueue aufrufen, egal wo. (in Threads verhält es sich gleich, nur im Hauptthread macht es "auch" das, was man sich vom "Queue" denken würde)
TThread.Queue verhält sich im Hauptthread aufgerufen wie ein Synchronize. Synchronisation: (egal ob Queue oder Synchronize) * alles im Hauptthread, da ist es nutzlos (bzw. bringt nur unnötig Overhead) * zwischen Thread geht es * zwischen Thread(s) und Hauptthread ... im Hauptthread ist es unnötig, da Jener sowieso gerade "blockiert" ist (aber als Doku, bzw. damit es überall gleich ist, würde ich es im Hauptthread als "vertretbar" ansehen) |
AW: Fenster schließt sich nicht
Zitat:
|
AW: Fenster schließt sich nicht
Zitat:
|
AW: Fenster schließt sich nicht
ForceQuere zu erfinden war eh eine blöde Idee.
Wäre schöner gewesen sie hätten Queue repariert. |
AW: Fenster schließt sich nicht
Zitat:
Damit hätten sie die Kompatibilität gebrochen und alte Quelltexte hätten nicht mehr funktioniert. |
AW: Fenster schließt sich nicht
Ich bin da voll bei Sebastian. Niemand hatte Queue in der Form verwendet, die ForceQueue implementiert. Hätten Sie Queue geändert, hätten einige ihren Quelltexte ändern müssen. Nun hat man die Wahl - finde ich besser als den potentiellen Ärger bei einem Breaking Change.
|
AW: Fenster schließt sich nicht
Zitat:
Dafür ist es super geeignet :stupid: Vielleicht passt der Name dafür nicht ganz. |
AW: Fenster schließt sich nicht
Wer ruft denn Queue im Hauptthread auf und wozu?
Queue macht dort quasi ein Synchronize, und wer Synchronize haben will, der kann auch direkt Synchronize benutzen. Wobei Synchronize im Hauptthread nutzlos ist, da es nichts Anderes macht, als den Code "jetzt" auszuführen (auf sich selber zu warten wäre eh irrsinnig) und das kann man auch einfacher haben, indem man weder Synchronize, noch Queue benutzt. TThread.Queue "bedeutet" doch IMHO "führe nicht jetzt aus, sondern später", und das macht Queue ja schließlich nicht, innerhalb des Hauptthreads. :freak: |
AW: Fenster schließt sich nicht
Zitat:
|
AW: Fenster schließt sich nicht
Ich verstehe den Sinn der ganzen Diskussion nicht. Es ist doch vollkommen irrelevant ob die Queue-Implementierung richtig oder falsch war/ist - sie ist einfach Fakt, dokumentiert und eine Reihe von Programmierern verlässt sich darauf. Die Entscheidung für ein ForceQueue (oder wie man es auch nennen will) war die einzige Möglichkeit, die gewünschte Funktionalität bereitzustellen ohne bestehenden Code in fehlerhaften Code zu verwandeln. Es gibt schon genug Fälle, in denen das nicht so gehandhabt wurde.
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:30 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