Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Auf Abmelden/Herunterfahren in onClose reagieren (https://www.delphipraxis.net/142347-auf-abmelden-herunterfahren-onclose-reagieren.html)

The_Unknown 26. Okt 2009 20:42


Auf Abmelden/Herunterfahren in onClose reagieren
 
Hallo,

ich versuche gerade, folgendes zu bewerkstelligen:
Mein Programm öffnet im onClose-Event des Hauptformulars eine Messagebox. Diese soll allerdings nur kommen, wenn das Programm "von Hand" beendet wird, nicht aber, wenn Windows gerade am Herunterfahren/Abmelden/Neustarten ist, schließlich will ich ja nicht das Herunterfahren verhindern ;)

Ich habe es schon mit WM_QUERYENDSESSION versucht, aber das Event wird erst *nach* dem onClose-Event ausgelöst.

Gibt es eine Möglichkeit, es anders hinzubekommen?

Thx!

Tschüss The_Unknown

thkerkmann 26. Okt 2009 20:51

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Hi,

Du musst das OnCloseQuery Event nehmen, das kommt vorher.

Gruss

The_Unknown 26. Okt 2009 21:22

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Und wie stelle ich dann im onCloseQuery-Event fest, ob gerade heruntergefahren/abgemeldet/neugestartet wird?

mkinzler 26. Okt 2009 21:24

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Der Event wird aufgerufen, wenn die Beendigung des Programmes verlangt wird

The_Unknown 26. Okt 2009 21:34

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Aber das Event wird doch auch dann aufgerufen, wenn ich das Programm "von Hand" beende, sprich das kleine X oben rechts anklicke. Und genau hier soll ja unterschieden werden, ob der Rechner gerade am Herunterfahren ist oder nicht.

XXcD 26. Okt 2009 21:58

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Ich hoffe der folgende Link hilft dir weiter:
http://www.delphipraxis.net/internal...ect.php?t=4047

gmc616 26. Okt 2009 22:02

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
kannst du nicht im WM_QUERYENDSESSION einen Boolean setzen, denn du im OnClose bzw. OnCloseQuery auswertest?

The_Unknown 26. Okt 2009 22:05

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Zitat:

Zitat von gmc616
kannst du nicht im WM_QUERYENDSESSION einen Boolean setzen, denn du im OnClose bzw. OnCloseQuery auswertest?

:gruebel: Naja, das ist, wie ich oben bereits geschrieben hatte, die falsche Reihenfolge, denn QueryEndSession kommt erst *nach* onClose, wenn es also schon zu spät ist.

Zitat:

Zitat von XXcD
Ich hoffe der folgende Link hilft dir weiter:
http://www.delphipraxis.net/internal...ect.php?t=4047

Das hilft mir dementsprechend auch nicht weiter :(

gmc616 26. Okt 2009 22:22

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Zitat:

Zitat von The_Unknown
:gruebel: Naja, das ist, wie ich oben bereits geschrieben hatte, die falsche Reihenfolge, denn QueryEndSession kommt erst *nach* onClose, wenn es also schon zu spät ist.

Hmpf ... :gruebel:

Bei mir nicht. Alles so wie' sein soll.

WMQUERYENDSESSION
OnCloseQuery
OnClose

Wäre irgendwie auch doof, wenn Windows das Programm beendet und danach erst fragt, oder ?

The_Unknown 26. Okt 2009 22:31

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Mhm, bei mir (Windows 7 x64):
OnCloseQuery
WM_QueryEndSession

Nur weiß ich nicht, ob das immer und bei jedem so ist. Anscheinend ja nicht :gruebel:

Gibts vielleicht noch eine andere Variante, das zu lösen?

Dezipaitor 26. Okt 2009 22:40

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Schau mal, ob
Delphi-Quellcode:
if GetSystemMetrics(SM_SHUTTINGDOWN) <> 0 then
  //is shutting down
(erst ab XP) dir weiterhilft.
Ich bin mir aber nicht sicher, ob das auch bei Neustart funktioniert.

The_Unknown 26. Okt 2009 22:44

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Nope, leider nicht. Das Abmelden z.B. wird nicht erkannt.

BerndS 27. Okt 2009 13:06

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Hallo
bei mir ist das so gelöst und klappt bisher ganz gut.


Delphi-Quellcode:
procedure TMainForm.FormCreate(Sender: TObject);
begin
  ...
  Application.HookMainWindow(WMEndSession);
  ...
end;

procedure MainForm.FormDestroy(Sender: TObject);
begin
  ...
  Application.UnhookMainWindow(WMEndSession);
  ...
end;

function TMainForm.WMEndSession(var Message: TMessage):Boolean;
begin
  if (Message.Msg=WM_ENDSESSION) and TWMEndSession(Message).EndSession then
  begin
    SessionEnd:=True; // diese kann dann ausgewertet werden
    ...
  end;
  Result:=False;
end;
Gruß Bernd

The_Unknown 27. Okt 2009 16:28

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Das sieht schon mal ganz gut aus, es tritt aber ein seltsamer Fehler auf. Ich habe es nun so gemacht:
Delphi-Quellcode:
function TForm1.WMEndSession(var Message: TMessage):Boolean;
begin
  if (Message.Msg=WM_ENDSESSION) and TWMEndSession(Message).EndSession then
  begin
    SessionEnd := True; // diese kann dann ausgewertet werden
  end;
  Result:=False;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  showmessage(inttostr(Integer(SessionEnd)));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
Application.HookMainWindow(WMEndSession);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
Application.UnhookMainWindow(WMEndSession);
end;
Wenn ich die Anwendung normal über "X" beende, kommt die Meldung 0, also alles ok.
Wenn ich nun aber zB. abmelde, kommt überhauptkeine Message (weder 0 noch 1), was ja nicht sein kann, denn ich habe in der Showmessage ja was stehen!?

ringli 27. Okt 2009 16:53

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Also ich habe es bei mir so gemacht. Vielleicht hilft dir das ja weiter:
Delphi-Quellcode:
procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
var
  Button : Word;
begin
  Button := MessageBox(Handle,
                       PChar('Beenden?'),
                       PChar('Ende der Anwendung'),
                       MB_YESNO or MB_ICONQUESTION);

  case Button of
    mrNo :
      begin
        Action := caNone;
        Application.Minimize;
        end;
    mrYes :
      begin
        Action := caFree;
      end;
  end;
end;

The_Unknown 27. Okt 2009 16:57

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Das hilft nicht wirklich weiter.

Ich schildere am besten mal, was ich genau damit machen will. Ich möchte, wenn ich das MainForm schließe, dass eine Nachricht kommt "Achtung: Das Programm ist immernoch geöffnet, nur dass es jetzt neben der Systemuhr ist..." (die Nachricht kommt natürlich nur 1x und dann nie wieder). Wenn nun allerdings der User herunterfährt und das Hauptfenster ist noch offen und die Meldung wurde noch nie angezeigt, dann kommt die Meldung beim Herunterfahren, was etwas unglücklich ist.

Ich hoffe, nun ist es klarer ;)

thkerkmann 27. Okt 2009 18:57

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Hi,
ich denke Du solltest mal dies versuchen:

Delphi-Quellcode:
Interface

  Type
    tForm1 = class(TForm)
    ...
      procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
   private
     FEndSession: boolean;
     TrayMessageDone: boolean;
   protected
      procedure WMQueryEndSession(var msg: tMessage); message WM_QUERYENDSESSION;
      procedure WMEndSession(var msg: tMessage); message WM_ENDSESSION;



   end;

Implementation

procedure tForm1.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
begin
  CanClose := FEndSession; // wenn endsession flag gesetzt, dann kompromisslos beenden
  if not CanClose then
  begin
    if not TrayMessageDone then
    begin
      TrayMessageDone := true;
      showmessage('wir gehen jetzt in den Tray');
    end;
    // minimieren oder in den tray legen.
    Hide;
  end;
end;

procedure tForm1.WMEndSession(var msg: tMessage);
begin
  FEndSession := bool(msg.wParam);
  if FEndSession then
  begin
    // aufräumarbeiten durchführen
    // ich lagere diese in eine Prozedur Finish aus, und rufe sie hier und im FormDestroy auf.
    // achtung - nur einmal aufrufen - flag setzen
  end;
  msg.result := 0;
end;

procedure tForm1.WMQueryEndSession(var msg: tMessage);
begin
  FEndSession := true;
  bool(msg.result) := TRUE;
end;
ungetestet, aber ähnlich mache ich es in meinen Programmen auch - ausser der TrayMessage.

Gruss

Blup 28. Okt 2009 07:03

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Zitat:

Zitat von The_Unknown
Wenn ich die Anwendung normal über "X" beende, kommt die Meldung 0, also alles ok.
Wenn ich nun aber zB. abmelde, kommt überhauptkeine Message (weder 0 noch 1), was ja nicht sein kann, denn ich habe in der Showmessage ja was stehen!?

Wenn die Session tatsächlich beendet wird, zeigt Windows neuen Fenster nicht mehr an.

ChrisE 28. Okt 2009 08:50

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von The_Unknown
Wenn ich die Anwendung normal über "X" beende, kommt die Meldung 0, also alles ok.
Wenn ich nun aber zB. abmelde, kommt überhauptkeine Message (weder 0 noch 1), was ja nicht sein kann, denn ich habe in der Showmessage ja was stehen!?

Wenn ich mich richtig erinnere, hatte ich ein ähnliches Problem. Und soweit ich noch weiß wurde OnClose nicht mehr ausgelöst, wenn der Rechner abgemeldet/heruntergefahren wurde.

Also soweit ich mich richtig erinnere war es so:
[X] am Fenster:
OnCloseQuery
OnClose
OnDestroy

Abmelden/Herunterfahren:
WM_QUERYENDSESSION
OnCloseQuery
WM_ENDSESSION
OnDestroy

Und soweit ich die Hilfe von M$ richtig verstanden habe, steht ja zum Zeitpunkt von WM_QUERYENDSESSION nicht fest ob wirklich herunter gefahren wird. Es wird ja nur nach gefragt ob es gehen würde. Es könnte auch noch abgebrochen werden von einer anderen Anwendung.

Und es gab noch einen merkwürdigen Effekt. Beim schließen über [X] wurde OnCloseQuery nur vom MainForm ausgelöst während beim Herunterfahren/Abmelden alle Forms des Projekts die ein OnCloseQuery hatten abgefragt wurden. Hatte bei mir sogar das Herunterfahren verhindert :-(

Gruß, Chris

[Edit] Hab nochmal das DemoProjekt nachgebaut, welches meine These unterstützt :-)[/Edit]

The_Unknown 28. Okt 2009 12:53

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Ja, genau dieses Problem habe ich bei mir auch.

Nur wenn ich herunterfahre, und ich habe bei onCloseQuery showmessage('Hallo'); drin stehen, dann poppt diese meldung beim Herunterfahren auch nicht auf.

Ich bin langsam wirklich etwas ratlos in dieser Sache.

ChrisE 28. Okt 2009 15:57

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Folgendes solltest du doch jetzt lösen können:

Wenn du wie in meinem Beispielprojekt deinem MainForm eine WMQueryEndSession verpasst kannst du bei WM_QUERYENDSESSION ja zuerst eine Boolsche Variable setzen. Der Trick ist erst die Variable setzten und dann erst inherited auf zu rufen :-)
Delphi-Quellcode:
procedure TMainForm.WMQueryEndSession(var Message: TMessage);
begin
  FWmQueryEndsession := TRUE;
  inherited;
end;
Wenn du jetzt in deine CloseQuery kommst dort einfach nur abfragen ob die Var gesetzt ist. Wenn ja, dann kommt der Aufruf zum schließen wohl nicht vom Anwender per [X]-Knopf sondern vom System wegen Abmelden / Runterfahren.

Denn du willst es ja glaube ich genau so, oder? ->
Zitat:

Zitat von The_Unknown
Ich möchte, wenn ich das MainForm schließe, dass eine Nachricht kommt "Achtung: Das Programm ist immernoch geöffnet, nur dass es jetzt neben der Systemuhr ist..." (die Nachricht kommt natürlich nur 1x und dann nie wieder). Wenn nun allerdings der User herunterfährt und das Hauptfenster ist noch offen und die Meldung wurde noch nie angezeigt, dann kommt die Meldung beim Herunterfahren, was etwas unglücklich ist.

Greez, Chris

The_Unknown 31. Okt 2009 19:13

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Jetzt funktioniert es tatsächlich :thumb:

Kann es sein, dass inherited; den Konstruktor der Superklasse von WMQUERYENDESSEION aufruft (ähnlich zu super(); in Java)?

Jetzt fehlt mir nur noch eine Antwort auf ein weiteres - anscheinend nicht minder verzwicktes - Problem, wo mir niemand antwortet :(
--> http://www.delphipraxis.net/internal...094740#1094740

Jakson 18. Jan 2010 12:59

Re: Auf Abmelden/Herunterfahren in onClose reagieren
 
Hi

Wie kann ich den erkennen ob nach dem ich das WM_QUERYENDSESSION reagiert habe (IsShutingDown = True) wer anderer das Herunterfahren abgebrochen hat?

Gibts da ein WM_ContinueSession oder so auf das ich reagieren könnte?

Danke Jakson

[edit]
Ich hab die frage noch einmal in einem neuen Thread gestellt http://www.delphipraxis.net/internal...121830#1121830
[/edit]


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:48 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