Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Windows beendet Programm nicht (https://www.delphipraxis.net/51124-windows-beendet-programm-nicht.html)

Matze 6. Aug 2005 12:22


Windows beendet Programm nicht
 
Moin!

Ich habe etliche Möglichkeiten schon durch probiert, die hier im Forum auch genannt werden, doch keine schafft es Windows nicht, mein Programm beim Herunterfahren zu beenden. Windows lässt sich folglich erst herunterfahren, wenn ich das Programm manuell beende.

Hier die mir am einleuchtesten erscheinende, nicht funktionierende Möglichkeit:

Delphi-Quellcode:
procedure WMQUERYENDSESSION(var msg: TMessage); message WM_QUERYENDSESSION;

[...]

procedure TForm1.WMQUERYENDSESSION(var msg: TMessage);
begin
  inherited;

  //Falls eingestellt, dass das Programm bei Klick auf "X" minimiert werden soll
  MinimizeAtClose := false;

  //Falls eingestellt, dass Nachfrage beim Beenden erscheint
  AskForClose := false;

  msg.Result := 1;
end;
Die evtl. relevanten Stellen meines Code sehen wie folgt aus:

Delphi-Quellcode:
//TNA - auf Mausklicks reagieren:
procedure TForm1.WndProc(var Msg: TMessage);
var
  Point: TPoint;
begin
  if Msg.Msg = WM_USER + 20 then
  begin
    case Msg.lParam of
      WM_RBUTTONDOWN:
        begin
          SetForegroundWindow(Handle);
          GetCursorPos(Point);
          PopUpMenu1.PopUp(Point.X, Point.Y);
        end;
      WM_LBUTTONDBLCLK:
        begin
          Form1.Show;
          Shell_NotifyIcon(NIM_DELETE, @IconData);
        end;
    end;
  end;
  inherited;
end;
Delphi-Quellcode:
//Beim Minimieren Icon in TNA:
procedure TForm1.WMSysCommand(var Message: TWMSysCommand);
begin
  if Message.CmdType and $FFF0 = SC_MINIMIZE then
  begin
    MinimizeToTray;
  end
  else
    inherited;
end;
Delphi-Quellcode:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  if AskForClose and (not MinimizeAtClose) then
  begin
    if Application.MessageBox('Programm beenden?', 'Hinweis', MB_YESNO) = IDYes then
    begin
      AskForClose := false;
      MinimizeAtClose := false;
      CanClose := true;
      Application.MainForm.Close;
    end else
      CanClose := false;
  end;
end;
Sieht jemand von euch da einen Fehler? Ich kann beim besten Willen keinen entdecken.

turboPASCAL 6. Aug 2005 12:53

Re: Windows beendet Programm nicht
 
Weil CanClose := false; gesetzt ist auch bei der WM_QueryEndSession Message ?

Flocke 6. Aug 2005 12:59

Re: Windows beendet Programm nicht
 
Nur 'n paar Gedanken...

1. Schießt du dir bei <HIER> nicht selbst in den Hintern? Du bist doch schon im Close weil CloseQuery aufgerufen wurde.

Zitat:

Zitat von Matze
Delphi-Quellcode:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  if AskForClose and (not MinimizeAtClose) then
  begin
    if Application.MessageBox('Programm beenden?', 'Hinweis', MB_YESNO) = IDYes then
    begin
      AskForClose := false;
      MinimizeAtClose := false;
      CanClose := true;
      Application.MainForm.Close; // <--- HIER
    end else
      CanClose := false;
  end;
end;

2. Reagiere nicht auf WM_QUERYENDSESSION sondern auf WM_ENDSESSION mit wParam<>0 -> Application.MainForm.Close oder Application.Terminate

3. Wenn das nichts hilft würde ich mir in WndProc einen Logger packen, der alle Fenstermeldungen mitschreibt. Dann weißt du mal, was so ein Windows Shutdown überhaupt an Meldungen verursacht.

Ansonsten wüsste ich nicht, was den Shutdown aufhalten sollte. Was klappt denn nicht, kommt die Rückfragebox?

Matze 6. Aug 2005 15:05

Re: Windows beendet Programm nicht
 
Zitat:

Zitat von turboPASCAL
Weil CanClose := false; gesetzt ist auch bei der WM_QueryEndSession Message ?

Ich denke eigentlich, dass die WM_QueryEndSession-Message eintritt, bevor das OnCloseQuery-Ereignis aufgerufen wird. Ich stelle bei der Message ja die boolschen Variablen auf false. Wenn danach dann das OnCloseQuery kommt, steht CanClose ja auf true.

Zitat:

Zitat von Flocke
Schießt du dir bei <HIER> nicht selbst in den Hintern?

Tatsache, da hatte ich einen Fehler drin, danke, nur lag's nicht an dem.

Zitat:

Zitat von Flocke
Reagiere nicht auf WM_QUERYENDSESSION sondern auf WM_ENDSESSION mit wParam<>0 -> Application.MainForm.Close oder Application.Terminate

Wieso das?
Dann kann ich ja nicht mehr entsprechend reagieren.

Zitat:

Zitat von Flocke
Wenn das nichts hilft würde ich mir in WndProc einen Logger packen, der alle Fenstermeldungen mitschreibt. Dann weißt du mal, was so ein Windows Shutdown überhaupt an Meldungen verursacht.

Ich schau mal, wie das geht, vielleicht komme ich dann zu einer Lösung.

Zitat:

Zitat von Flocke
Was klappt denn nicht, kommt die Rückfragebox?

Nein, es kommt gar nichts. Das Programm läuft weiter, als ob sein Chef (Windows) nichts gesagt hätte. ;)

Ich habe auch testweise ShowMessage in der WMQUERYENDSESSION Prozedur und im OnCloseQuery aufgerufen, doch sehe ich nie einen Dialog. Evtl. tritt das Ereignis gar nicht erst ein. :gruebel:

turboPASCAL 6. Aug 2005 15:28

Re: Windows beendet Programm nicht
 
Zitat:

Zitat von Matze
Zitat:

Zitat von turboPASCAL
Weil CanClose := false; gesetzt ist auch bei der WM_QueryEndSession Message ?


Ich denke eigentlich, dass die WM_QueryEndSession-Message eintritt, bevor das OnCloseQuery-Ereignis aufgerufen wird. Ich stelle bei der Message ja die boolschen Variablen auf false. Wenn danach dann das OnCloseQuery kommt, steht CanClose ja auf true.

Auwaija, ich glaube ich hatte ein END; übersehen. :spin:

Was haste denn für ein OS ?

Matze 6. Aug 2005 15:42

Re: Windows beendet Programm nicht
 
Zitat:

Zitat von turboPASCAL
Was haste denn für ein OS ?

Windows XP Home SP2

Also mein Msg-Log zeigt, dass folgende Messages aufgerufen werden (lParam):

Zitat:

0, 1, 1239556, 1240484, 1240528, 1241896, 1241952, 1241972, 1242004, 1242100, 1242968, 1243456, 1243896, 1243932, 1243940, 1376837, 9647792, 12321082, 12321301, 12779825, 13697557, 1244844, 316, 11469105, 1243568, 1243612, 1243920, 15008277, 1716, 1769796
Wohl am wichtigsten: Gegen Ende des Programmes:

Zitat:

512, 516, 517, 9647952, 9654092
Kann man irgendwo nachsehen, was welche Message ist? Im MSDN finde ich dazu nichts.

turboPASCAL 6. Aug 2005 16:03

Re: Windows beendet Programm nicht
 
http://www.swissdelphicenter.ch/torr...ode.php?id=939

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

Implementation

procedure TForm1.WMQueryEndSession (var Msg : TWMQueryEndSession);
begin
  if MessageDlg('Close Windows now/ Windows beenden?',
                            mtConfirmation,
                            [mbYes,mbNo], 0) = mrNo then
      Msg.Result := 0
   else
      Msg.Result := 1;
end;

Matze 6. Aug 2005 16:09

Re: Windows beendet Programm nicht
 
Das habe ich auch schon versucht, danke, nur ändert das auch nichts. Ich verstehe das absolut nicht.

TStringlist 6. Aug 2005 16:19

Re: Windows beendet Programm nicht
 
Die Flags (MinimizeAtClose u. AskForClose) müsstest du eigentlich vor dem inherited setzen, da FormCloseQuery nämlich in Delphis eigenen QueryEndSession-Handler aufgerufen wird (und dieser Handler selbst wieder durch das inherited).

TStringlist 6. Aug 2005 16:54

Re: Windows beendet Programm nicht
 
Zitat:

Zitat von Matze
Ich habe auch testweise ShowMessage in der WMQUERYENDSESSION Prozedur und im OnCloseQuery aufgerufen, doch sehe ich nie einen Dialog. Evtl. tritt das Ereignis gar nicht erst ein.

Das wäre eigentlich nur dann möglich, wenn deine Application noch mehr Formen hätte und eine davon die QueryEndSession-Message davor schon bekommen und diese mit False beantwortet hätte. (Das wäre z.B. auch schon dann der Fall, wenn du dort auch schon nur zufälligerweise eine ganz leere << procedure TForm1.WMQUERYENDSESSION(var msg: TMessage); begin end; >> stehen hättest).

Normalerweise bekommen nämlich alle Formen einer Application eine solche Message zugeschickt und nur dann, wenn alle sie mit True beantwortet haben, deaktiviert die Application anschließend auch. Beantwortet nur eine Form diese Message mit false, bekommen die weiteren Formen keine QueryEndSession-Message mehr und die Application bleibt am Leben.


(hoffe ich erzähle hier keinen Bockmist, glaube es aber nicht :-))

Flocke 6. Aug 2005 22:19

Re: Windows beendet Programm nicht
 
Zitat:

Zitat von TStringlist
Das wäre eigentlich nur dann möglich, wenn deine Application noch mehr Formen hätte und eine davon die QueryEndSession-Message davor schon bekommen und diese mit False beantwortet hätte.

:wall: Guter Tipp!
Als ich das gelesen habe ist mir siedend heiß eingefallen, dass das Hauptfenster von Delphi-Anwendungen ja ein unsichtbares ist (darum können Application.Title und MainForm.Caption unterschiedlich sein!).

Du kriegst gar kein WM_QUERYENDSESSION / WM_ENDSESSION, weil dein Hauptfenster nicht das Hauptfenster der Anwendung ist!

[... ich schau gerade mal in der OH ...]

Hmmm... in TApplication.WndProc in Forms.pas sieht das so aus:
Delphi-Quellcode:
WM_ENDSESSION:
  if TWMEndSession(Message).EndSession then
  begin
    CallTerminateProcs;
    Halt;
  end;
WM_QUERYENDSESSION:
  Message.Result := 1;
Sollte normalerweise also alles funktionieren...

Flocke 6. Aug 2005 22:31

Re: Windows beendet Programm nicht
 
Noch was (sorry für zwei Posts hintereinander)

Zitat:

Zitat von Matze
Also mein Msg-Log zeigt, dass folgende Messages aufgerufen werden (lParam):

Zitat:

0, 1, 1239556, 1240484, 1240528, 1241896, 1241952, 1241972, 1242004, 1242100, 1242968, 1243456, 1243896, 1243932, 1243940, 1376837, 9647792, 12321082, 12321301, 12779825, 13697557, 1244844, 316, 11469105, 1243568, 1243612, 1243920, 15008277, 1716, 1769796
Wohl am wichtigsten: Gegen Ende des Programmes:

Zitat:

512, 516, 517, 9647952, 9654092
Kann man irgendwo nachsehen, was welche Message ist? Im MSDN finde ich dazu nichts.

Kannst du in Message.pas nachschlagen.
Code:
512      $0200   WM_MOUSEMOVE
516      $0200   WM_RBUTTONDOWN
517      $0200   WM_RBUTTONUP
9647952  $933750 ??? RegisterWindowMessage
9654092  $934F4C ??? RegisterWindowMessage
Kann nicht viel daraus erkennen. Die beiden hohen Meldungsnummer scheinen mit RegisterWindowMessage registriert worden zu sein.

Evtl. sind Fenstermeldungen auch Atoms und du kannst den Namen über GlobalGetAtomName ermitteln.

gsh 6. Aug 2005 22:37

Re: Windows beendet Programm nicht
 
ich muss ehrlich sein ich verstehe nicht alles was ihr da mit WM_QUERYENDSESSION und WM_ENDSESSION und so weiter redet aber ich hatte einmal mit meinem Prog. ganz genau des gleiche Problemm. Es war ein kleines Prog. des im hintergrund lief und mir eine Meldung gab wenn ich ein neues e-mail in meiner Mailbox hatte aber als ich des Windows XP auschalten wollte weigerte es sich ganz penetrant dagegen ich hab echt ewig meinen source durchsucht (es war ja nicht viel) aber nichts.

Nur durch diesen Code zog des Prog. dann endlich beim beenden mit:
Delphi-Quellcode:
procedure TForm1.WMQueryEndSession(var M: TWMQueryEndSession);
begin
  inherited;
  close;
end;


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

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