Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Fenster schließt sich nicht (https://www.delphipraxis.net/212873-fenster-schliesst-sich-nicht.html)

TurboMagic 16. Apr 2023 19:28

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

peterbelow 16. Apr 2023 19:31

AW: Fenster schließt sich nicht
 
Setz einfach ModalResult := mrOK; bei modalen Fenstern funktioniert Close nicht ganz so wie bei nicht-modalen.

himitsu 16. Apr 2023 20:16

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:
ModalResult := mrCancel;
, also funktional kein Unterschied zu deinem Lösungsvorschlag.




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.

TurboMagic 16. Apr 2023 20:25

AW: Fenster schließt sich nicht
 
Danke für die Tipps, werde ich baldmöglichst mal ausprobieren...

BerndS 16. Apr 2023 22:19

AW: Fenster schließt sich nicht
 
Zitat:

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)
Nicht dein Ernst, bei von mir verwendeten Dialogen funktioniert das zuverlässig seit Delphi 2.

Uwe Raabe 16. Apr 2023 23:12

AW: Fenster schließt sich nicht
 
Zitat:

Zitat von himitsu (Beitrag 1521117)
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)

Wie Bernd schon sagte, das funktioniert in der Tat so wie erwartet - und das zumindest schon ziemlich lange. Man braucht auch nur in die Sourcen zu schauen.
Delphi-Quellcode:
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;
Sollte das bei dir nicht funktionieren, dann liegt das vermutlich nicht an Delphi. Vielleicht stimmt auch was mit deinem TestCase nicht.

himitsu 17. Apr 2023 00:26

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?


https://quality.embarcadero.com/brow...2CloseModal%22


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:
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;
Echt mal, warum kann man nicht an der Stelle einen Kommentar rein tun?
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.

BerndS 17. Apr 2023 07:19

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:
    try
      Show;
      try
        SendMessage(Handle, CM_ACTIVATE, 0, 0);
        ModalResult := 0;
        repeat
          ...
          ...
        until ModalResult <> 0;
Wenn man die Form im OnShow oder OnAvtivate schließen möchte, dann per

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.

Uwe Raabe 17. Apr 2023 07:50

AW: Fenster schließt sich nicht
 
Zitat:

Zitat von himitsu (Beitrag 1521126)
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:

Welche Stelle genau meinst du?

himitsu 17. Apr 2023 11:43

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

QuickAndDirty 17. Apr 2023 12:41

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.

himitsu 17. Apr 2023 13:58

AW: Fenster schließt sich nicht
 
Statt PostMessage und Timer verwende ich hier gern das Thread.Queue

Delphi-Quellcode:
TThread.ForceQueue(nil, procedure // im OnShow oder OnCreate/Create
  begin
    ...
  end);
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)

jaenicke 17. Apr 2023 18:23

AW: Fenster schließt sich nicht
 
Zitat:

Zitat von himitsu (Beitrag 1521148)
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)

Ich verwende diese Funktionalität allerdings auch, um Zugriffe threadsicher zu machen. Ich kann so einfach Queue aufrufen, ohne zu prüfen, ob ich schon im Hauptthread bin. Deshalb hätte ich es schlecht gefunden, wenn das geändert worden wäre, auch wenn ich deine Argumentation natürlich verstehe.

himitsu 17. Apr 2023 19:01

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)

TurboMagic 17. Apr 2023 20:16

AW: Fenster schließt sich nicht
 
Zitat:

Zitat von himitsu (Beitrag 1521148)
Statt PostMessage und Timer verwende ich hier gern das Thread.Queue

Delphi-Quellcode:
TThread.ForceQueue(nil, procedure // im OnShow oder OnCreate/Create
  begin
    ...
  end);
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)

Danke, ForceQueue funktioniert!

jaenicke 17. Apr 2023 21:49

AW: Fenster schließt sich nicht
 
Zitat:

Zitat von himitsu (Beitrag 1521163)
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)

Das möchte ich an der Stelle aber gar nicht. ;-) Und ich (und auch viele andere, wenn ich so fremde Quelltexte anschaue) verlasse mich darauf, dass das auch so bleibt.

himitsu 18. Apr 2023 06:29

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.

jaenicke 18. Apr 2023 06:59

AW: Fenster schließt sich nicht
 
Zitat:

Zitat von himitsu (Beitrag 1521178)
Wäre schöner gewesen sie hätten Queue repariert.

Wie schon geschrieben:
Damit hätten sie die Kompatibilität gebrochen und alte Quelltexte hätten nicht mehr funktioniert.

Uwe Raabe 18. Apr 2023 07:56

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.

Rollo62 18. Apr 2023 14:46

AW: Fenster schließt sich nicht
 
Zitat:

Zitat von himitsu (Beitrag 1521178)
ForceQuere zu erfinden war eh eine blöde Idee.

Ich bin da ganz froh drum, das nutze ich gerne zum zeitlichen Entkoppeln.
Dafür ist es super geeignet :stupid: Vielleicht passt der Name dafür nicht ganz.

himitsu 18. Apr 2023 15:46

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:

jaenicke 18. Apr 2023 15:53

AW: Fenster schließt sich nicht
 
Zitat:

Zitat von himitsu (Beitrag 1521207)
Wer ruft denn Queue im Hauptthread auf und wozu?

Wie gesagt, damit ich nicht selbst eine Variable für die anonyme Funktion anlegen und dann im Hauptthread direkt ausführen und ansonsten mit Queue ausführen muss. Da Queue sich da selbst drum kümmert, nutze ich dafür immer einfach das. ForceQueue brauche ich viel seltener, denn die Abkopplung brauche ich meistens nicht.

Uwe Raabe 18. Apr 2023 16:03

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