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/)
-   -   Delphi WM_QUERYENDSESSION verwenden (https://www.delphipraxis.net/135423-wm_queryendsession-verwenden.html)

JFB 10. Jun 2009 15:51


WM_QUERYENDSESSION verwenden
 
Hallo,

vorweg: Ich weiß, dass es zu diesem Thema bereits unzählige Beiträge in diesem Forum gibt. Ich habe mich bereits stundenlang da durch gequält. Leider ohne greifbares Ergebnis.

Mein Problem ist folgendes:
Ich möchte meine Anwendung "geregelt" (alles Speichern usw.) beenden, wenn der Anwender Windows herunterfährt. Dafür habe ich z.B. folgendes in das Hauptformular meiner Anwendung eingebaut:

Delphi-Quellcode:
procedure WMQueryEndSession(var Msg:TWMQueryEndSession); message WM_QUERYENDSESSION;

procedure TFMain.WMQueryEndSession(var Msg:TWMQueryEndSession);
begin
  showmessage('***Ende***');
  Msg.Result := 1;
end;
Es scheint so zu sein, dass meine Anwendung die Nachricht nicht erhält, weder beim einfachen "Abmelden" noch beim "Herunterfahren". Jedenfalls wird ShowMessage nicht ausgeführt und Windows fährt nicht herunter.

Wer weiß, wie es richtig gemacht werden muss?

Gruß
Johann

Helmi 10. Jun 2009 15:58

Re: WM_QUERYENDSESSION verwenden
 
Hallo,

ich mach das in meinen Programmen immer so:

Delphi-Quellcode:
private
    procedure WMQueryEndSession(var Msg: TWMQueryEndSession); message WM_QueryEndSession;

{...}

procedure TMainForm.WMQueryEndSession (var Msg : TWMQueryEndSession);
begin
  //Windows erlauben zu beenden
  Msg.Result := 1;

  //Wenn Windows beendet wird, dann Variable auf true setzen
  Windows_Session_End := true;

  //Programm schliessen
  close;

  inherited;
end;
Mit der Variablen "Windows_Session_End" umgeh ich die Frage ob wirklich beendet werden soll, beim Schliessen des Programmes
und Speichere gleich drauf los

JFB 10. Jun 2009 16:04

Re: WM_QUERYENDSESSION verwenden
 
Hallo Helmi,

vielen Dank für deine Antwort. Mein Problem ist allerdings nicht, wie ich überflüssige Abfragen verhindere oder das Programm beende, sondern dass die Botschaft WM_QUERYENDSESSION scheinbar garnicht in meinem Programm ankommt.

Gruß
Johann

Blup 10. Jun 2009 16:44

Re: WM_QUERYENDSESSION verwenden
 
Wenn Windows nicht beendet wird, reagiert deine Anwendung offensichtlich auf diese Nachricht.

ShowMessage aufzurufen ist an dieser Stelle eine ganz schlechte Idee.
Diese Nachricht muss unverzüglich beantwortet werden.
Windows befindet sich sozusagen im Ausnahmezustand, bis alle Anwendungen reagiert haben.
Da darf man nicht einfach neue Fenster erstellen.
Wenn man das Beenden von Windows verhindert, kann man sich aber selbst noch schnell eine Nachricht Posten und nachträglich auf dieses Ereignis reagieren.

http://www.developia.de/forum/viewtopic.php?t=83552

JFB 10. Jun 2009 17:03

Re: WM_QUERYENDSESSION verwenden
 
@Blub

Wenn ich ShowMessage mal testweise durch close ersetze, passiert ebenfalls rein garnichts. Die Anwendung bleibt geöffnet, ist weiter bedienbar und Windows aktiv, so als ob ich garnichts gemacht hätte.
Übrigens: In einer kleinen Testanwendung, die nur aus dem Hauptfenster bestand, hat die Behandlung von WM_QUERYENDSESSION wunschgemäß funktioniert.

Gruß
Johann

Blup 11. Jun 2009 16:08

Re: WM_QUERYENDSESSION verwenden
 
Auch Close solltest du an dieser Stelle nicht aufrufen.
Windows hat noch nicht entschieden ob es beendet wird.
Es fragt alle Fenster ab und wenn auch nur eins mit 0 antwortet, passiert nichts.

Das ist die Standardantwort die jedes Fenster zurückgibt:
Delphi-Quellcode:
begin
  Msg.Result := 1;
end;
Das einzige sinnvolle andere Reaktion ist Result auf 0 zu setzen und/oder sich dieses Ereignis zu merken.
Der von Helmi gepostete Code gehört eigentlich in die Verarbeitung der Nachricht WM_EndSession.

Wenn deine Methode WMQueryEndSession entfernt wird und sich Windows trotzdem nicht beenden lässt, dann reagiert irgend ein anderes Fenster deiner Anwendung falsch auf diese Nachricht. Das kann auch ein unsichtbares Fenster sein, das z.B. von irgend einer Komponente/Klasse für interne Zwecke erzeugt wurde.

Helmi 11. Jun 2009 18:17

Re: WM_QUERYENDSESSION verwenden
 
Stimmt - Das close ist falsch.
Eigentlich kann man das close auch gleich vernachlässigen

Sir Rufo 11. Jun 2009 18:50

Re: WM_QUERYENDSESSION verwenden
 
Auch das Setzen des Flags "Windows_Session_End" ist formal gesehen falsch.

Denn hier steht, das nach WM_QUERYENDSESSION die Nachricht WM_ENDSESSION mit dem Ergebnis von WM_QUERYENDSESSION gesendet wird.

cu

Oliver

Helmi 11. Jun 2009 19:03

Re: WM_QUERYENDSESSION verwenden
 
Ich habs ausprobiert:
Bei WM_EndSession das Flag setzen ist zu spät

Ich habs daran gemerkt, dass meine Meldung, ob wirklich geschlossen werden soll, trotzdem kam, als ich Windows beendete
Mit dem Flag will ich das aber überbrücken.

Blup 12. Jun 2009 13:58

Re: WM_QUERYENDSESSION verwenden
 
Für eine Frage ob die Anwendung wirklich geschlossen werden soll, kenne ich in dieser Situation nur diese Variante.
Ist zwar umständlich, funktioniert aber sicher.

Wenn noch Daten in Bearbeitung sind die Nachricht mit 0 beantworten und dem eigenen Fenster eine Nachricht posten.
Diese Nachricht kann auch die Info enthalten, in welchen Modus Windows versetzt werden sollte (siehe unten).

Als Reaktion auf diese Nachricht dann die Frage nach dem Speichern/Beenden und wenn erfolgreich/ja anschließend Close.
Zum Schluss Windows selbst in den entsprechenden Modus versetzen oder diesen Schritt dem Anwender überlassen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:56 Uhr.

Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf