Entwickler-Ecke

Windows API - Win-Messages für ShutDown und Standby


Fabian W. - Sa 17.11.07 20:28
Titel: Win-Messages für ShutDown und Standby
2. Teil in Win-Message für WM_DEVICECHANGE [http://www.delphi-forum.de/viewtopic.php?p=472679].

Hallo,

seit langem habe ich auch mal wieder eine Frage.^^
Ich war mir nicht sicher ob ich 2 Topics machen sollte, man kann das Topic ja ggf spalten, denn im Grunde habe ich 2 Fragen:

a) Ich möchte die Messages für Shutdown und Standby abfangen und diese bestätigen oder ablehnen können. Ablehnen im Sinne von nicht runterfahren / kein Standby. Dazu habe ich folgenden Code gefunden:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
procedure Tform_haupt.WMQueryEndSession;
begin
  if MessageDLG('Windows beenden?', mtconfirmation, [mbyes, mbno], 0) = idyes then
    Msg.Result := 1   //Windows darf Runterfahren
  else
    Msg.Result := 0;  //Windows muss das Runterfahren stoppen
end;
// für standby dann eben:
procedure Tform_haupt.WMPowerBroadcast;
Ich bekomme auch eine entsprechende Meldung nur fährt der PC dennoch runter, wenn ich auf "Nein" drücke. Ist es möglich das Runterfahren zu verhindern?

Zu beidem habe ich nur spärliche und komplizierte Sachen gefunden. Entweder ich bin zu blöd zum Suchen oder es gibt dazu wirklich kaum Material. Danke schonmal für eure Hilfe!

mfg

Moderiert von user profile iconNarses: 2. Frage entfernt, Titel angepasst


Delete - Sa 17.11.07 20:40

Welches Betriebssystem? Bei Vista lässt sich das Runterfahren, meines Wissens nicht mehr so ohne weiteres abbrechen.


Fabian W. - So 18.11.07 08:58

Es geht mir hauptsächlich um XP, sollte es auch in früheren Versionen oder Vista gehen wär's schön, muss aber nicht sein.


Wotan89 - So 18.11.07 14:55

Für das Abbrechen habe ich folgenden Quelltext:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen } procedure WMQueryEndSession (var M: TWMQueryEndSession);  message WM_QUERYENDSESSION;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.WMQueryEndSession (var M: TWMQueryEndSession);
begin
inherited;
M.Result:=0;  //{Bei null bricht es ab und bei 1 fährt das System normal herunter}
end;

Bei mir klappt es auf jeden Fall


Fabian W. - So 18.11.07 17:52

Okay, beim Runterfahren klappst mit 0, bei

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure Tform_haupt.WMPowerBroadcast;
begin
  if (Msg.WParam = PBT_APMSUSPEND) or
     (Msg.WParam = PBT_APMSTANDBY) then
  begin
    if MessageDLG('Windows in Standby?', mtconfirmation, [mbyes, mbno], 0) = idyes then
      Msg.Result := 1   //Windows darf Runterfahren
    else
      Msg.Result := BROADCAST_QUERY_DENY;
  end;
end;
geht allerdings weder mit der o.g. Konstante oder 0. Kannst du das bei dir vlt auch kurz probieren? :)


Wotan89 - So 18.11.07 22:20

Für den Standbymodus klappt es bei mir so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private-Deklarationen } procedure WMPowerBrodacast(var m:TMessage);
    message WM_POWERBROADCAST;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.WMPowerBrodacast(var m:tmessage);
begin
inherited;
m.Result:=BROADCAST_QUERY_DENY;
end;

end.


Fabian W. - Mo 19.11.07 18:25

Das Problem bei WMPowerBrodacast ist, dass es oft ausgelöst wird, damit meine ich auch wenn der PC garnich in den Standby-Modus will oder beim Eintreten in den Modus. Deshalb sende ich nur eine Meldung wenn (Msg.WParam = PBT_APMSUSPEND) ODER (Msg.WParam = PBT_APMSTANDBY)ist. Wenn ich aber solche Messages verneine fährt der PC dennoch "runter".

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure Tform_haupt.WMPowerBroadcast;
begin
  if not form_options.cb_remindOnStandby.Checked then exit;

  if (Msg.WParam = PBT_APMSUSPEND) or
     (Msg.WParam = PBT_APMSTANDBY) then
  begin
    TrayIcon.BalloonHint('Vergessen Sie Ihr Speichermedium nicht!',
    'Windows soll in den Standby-Modus versetzt werden, aber ' + l_Device.Caption +
    ' ist noch angeschlossen!', btwarning, 15000, true);
    if MessageDLG('Windows soll in den Standby-Modus versetzt werden, aber ' + l_Device.Caption + ' ist noch angeschlossen. Windows dennoch beenden?', mtwarning, [mbyes, mbno], 0) = idyes then
      Msg.Result := 1   // Windows darf in Standby
    else
      Msg.Result := BROADCAST_QUERY_DENY;  // Windows darf nicht in Standby
  end;
end;
Auf welche Message müsste ich statt dessen reagieren, damit ein BROADCAST_QUERY_DENY Wirkung zeigt?


Wotan89 - Mo 19.11.07 22:32

Ich seh bei deiner Prozedur auch keine Messageverarbeitung! Anhand des Quelltextes den du mir zeigst müsstest du diesen Quelltext drauß machen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure Tform_haupt.WMPowerBroadcast(Msg:TMessage);
begin  
  if not form_options.cb_remindOnStandby.Checked then exit;  

 
  if (Msg.WParam = PBT_APMSUSPEND) or  
     (Msg.WParam = PBT_APMSTANDBY) then  
  begin  
    TrayIcon.BalloonHint('Vergessen Sie Ihr Speichermedium nicht!',  
    'Windows soll in den Standby-Modus versetzt werden, aber ' + l_Device.Caption +  
    ' ist noch angeschlossen!', btwarning, 15000, true);  
    if MessageDLG('Windows soll in den Standby-Modus versetzt werden, aber ' + l_Device.Caption + ' ist noch angeschlossen. Windows dennoch beenden?', mtwarning, [mbyes, mbno], 0) = idyes then  
      Msg.Result := 1   // Windows darf in Standby  
    else  
      Msg.Result := BROADCAST_QUERY_DENY;  // Windows darf nicht in Standby  
  end;  
end;

Hast du diese Prozedur auch in Privat mit procedure WMPowerBroadcast(Msg:TMessage); message WM_PowerBroadcast; geschrieben?


Fabian W. - Di 20.11.07 18:27

Nein, das mag zwar nicht ganz richtig sein verursacht aber den "Fehler" nicht. Shutdown tut ja auch. ;)
Es geht um das Selektieren der Message mit if (Msg.WParam = PBT_APMSUSPEND) or (Msg.WParam = PBT_APMSTANDBY) then. Ich vermunte, dass ich auf die falsche Message antworte, nun will ich wissen auf welche ich in der IF reagieren soll.


Wotan89 - Mi 21.11.07 13:57

Klar ich hatte was in meinem Quelltext vergessen: inherited muss mit dabei stehen.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
  private
    { Private-Deklarationen }   procedure WMPowerBroadcast(var Msg:TMessage); message WM_PowerBroadcast;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.WMPowerBroadcast(var Msg:TMessage);
begin
inherited;
Msg.Result:=BROADCAST_QUERY_DENY;
end;

end.

So funktioniert es auf jeden Fall! -> Also bei dir das inherited reinpacken ;)


Fabian W. - Mi 21.11.07 16:18

Nein, auch das inherited; ist nicht schuld. ;) Nun ließ dir bitte mal meine 2 letzten Posts durch und füge in deine Funtkion nen showmessage('sdf'); oder irgendwas ein. Dann wirst du sehen, dass die Message mehrmals gesendet wird.
Und nochmal: anscheinend sende ich mein "Nein" auf die falsche Message. Nun möchte ich wissen welche ich statt PBT_APMSUSPEND und PBT_APMSTANDBY sonst nehmen soll. ;)

mfg


Wotan89 - Mi 21.11.07 18:19

Ich hab es nochmal mit showmessage(inttostr(msg.wparam)) nachgeprüft und es müssten die beiden sein:
PBT_APMQUERYSUSPEND
PBT_APMQUERYSUSPENDFAILED
Ich hoffe es funktioniert!


Fabian W. - Fr 23.11.07 18:34

Fein, funktioniert, thxs :)