AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi WM_POWERBROADCAST wie verwenden?

WM_POWERBROADCAST wie verwenden?

Ein Thema von ULIK · begonnen am 30. Okt 2019 · letzter Beitrag vom 4. Mai 2020
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von ULIK
ULIK

Registriert seit: 25. Sep 2006
Ort: Regensburg
416 Beiträge
 
Delphi 11 Alexandria
 
#1

WM_POWERBROADCAST wie verwenden?

  Alt 30. Okt 2019, 10:01
Hallo,

ich habe eine wirklich dumme Frage: ich habe eine kleine Testanwendung, die nichts weiter machen soll, als auf WM_POWERBROADCAST Messages zu hören und in ein Memo zu schreiben, was empfangen wurde.

Delphi-Quellcode:
procedure TForm1.WMPowerbroadcast(var Message: TMessage);
begin
  memLog.Lines.Add('PowerBroadcast received');

  case Message.WParam of
    PBT_APMQUERYSUSPEND: memLog.Lines.Add('PBT_APMQUERYSUSPEND');
    PBT_APMQUERYSTANDBY: memLog.Lines.Add('PBT_APMQUERYSTANDBY');
    PBT_APMQUERYSUSPENDFAILED: memLog.Lines.Add('PBT_APMQUERYSUSPENDFAILED');
    PBT_APMQUERYSTANDBYFAILED : memLog.Lines.Add('PBT_APMQUERYSTANDBYFAILED');
    PBT_APMSUSPEND: memLog.Lines.Add('PBT_APMSUSPEND');
    PBT_APMSTANDBY: memLog.Lines.Add('PBT_APMSTANDBY');
    PBT_APMRESUMECRITICAL: memLog.Lines.Add('PBT_APMRESUMECRITICAL');
    PBT_APMRESUMESUSPEND: memLog.Lines.Add('PBT_APMRESUMESUSPEND');
    PBT_APMRESUMESTANDBY: memLog.Lines.Add('PBT_APMRESUMESTANDBY');
    PBT_APMBATTERYLOW: memLog.Lines.Add('PBT_APMBATTERYLOW');

    PBT_APMPOWERSTATUSCHANGE: memLog.Lines.Add('PBT_APMPOWERSTATUSCHANGE');
    PBT_APMOEMEVENT: memLog.Lines.Add('PBT_APMOEMEVENT');
    PBT_APMRESUMEAUTOMATIC: memLog.Lines.Add('PBT_APMRESUMEAUTOMATIC');
  end;
end;
Wenn ich das unter W10 laufen lassen und dann den Rechner in den Energiesparmodus oder Ruhemodus versetze, dann wird rein gar nichts aufgezeichnet. Auch ein Zuklappen des Laptopdeckels scheint keine Message zu generieren. Einzig wenn man das Netzteil an/absteckt, dann wir eine Message mit PBT_APMPOWERSTATUSCHANGE empfangen.

Ich nehm an, ich mach irgendeinen Fehler, nur welchen? Ich steh grad völlig auf dem Schlauch.

Ach so: Delphi ist XE 10.2.3

Geändert von ULIK (30. Okt 2019 um 10:02 Uhr) Grund: Delphiversion ergänzt
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
961 Beiträge
 
Delphi 6 Professional
 
#2

AW: WM_POWERBROADCAST wie verwenden?

  Alt 30. Okt 2019, 14:16
Hmm

Lies mal hier zu PBT_APMQUERYSUSPEND:

https://docs.microsoft.com/en-us/win...pmquerysuspend

Zitat:
Support for this event was removed in Windows Vista
https://docs.microsoft.com/en-us/win...powerbroadcast

WM_POWERBROADCAST scheint auch nur noch folgende event identifiers zu unterstützen:

PBT_APMPOWERSTATUSCHANGE
PBT_APMRESUMEAUTOMATIC
PBT_APMRESUMESUSPEND
PBT_APMSUSPEND
PBT_POWERSETTINGCHANGE


Auch kann seit Vista hiermit kein Suspend mehr damit unterbunden werden...
(Ja ich Verwende Delphi 6 Pro und will NICHT wechseln!)
  Mit Zitat antworten Zitat
Benutzerbild von ULIK
ULIK

Registriert seit: 25. Sep 2006
Ort: Regensburg
416 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: WM_POWERBROADCAST wie verwenden?

  Alt 30. Okt 2019, 14:48
Danke für den Hinweis. Inzwischen bin ich auch schlauer: selbst
PBT_APMRESUMEAUTOMATIC
PBT_APMRESUMESUSPEND
PBT_APMSUSPEND
werden nicht empfangen. Damit das wieder geht muß sich die Anwendung mit RegisterSuspendResumeNotification anmelden und entsprechend wieder abmelden (UnRegisterSuspendResumeNotification). Dies wäre angeblich seit Windows 8 so.
Dummerweise ist diese API nicht in Delphi 10.2 enthalten. Hab das mal selbst gemacht und siehe da, schon werden beim Schließen des Laptopdeckels wieder PBT_APMSUSPEND und anschließend beim Öffnen PBT_APMRESUMEAUTOMATIC und PBT_APMRESUMESUSPEND empfangen.

Hier mal etwas Code:
Delphi-Quellcode:
var
  hLibrary: THandle = 0;

  RegisterSuspendResumeNotification: function(hRecipient: THandle; flags: DWORD): HPOWERNOTIFY; stdcall = nil;
  UnRegisterSuspendResumeNotification: function(hNotification: HPOWERNOTIFY): Bool; stdcall = nil;

...

  hLibrary := LoadLibrary('user32.dll');
  if hLibrary <> 0 then
  begin
    RegisterSuspendResumeNotification := GetProcAddress(hLibrary, 'RegisterSuspendResumeNotification');
    UnRegisterSuspendResumeNotification := GetProcAddress(hLibrary, 'UnregisterSuspendResumeNotification');
  end;
Der Aufruf erfolgt dann z.B. im FormCreate mit hNotification := RegisterSuspendResumeNotification(Handle, DEVICE_NOTIFY_WINDOW_HANDLE); ; entsprechend dann UnRegisterSuspendResumeNotification(hNotification) im FormDestroy


Frohes Schaffen!
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.809 Beiträge
 
Delphi 12 Athens
 
#4

AW: WM_POWERBROADCAST wie verwenden?

  Alt 30. Okt 2019, 17:17
Wo in die Delphi RTL würden diese fehlenden API Deklarationen rein gehören?
Macht es Sinn, einen QP Feature request dazu zu erfassen?
  Mit Zitat antworten Zitat
Alt 30. Okt 2019, 17:32     Erstellt von Frühlingsrolle
Dieser Beitrag wurde von Daniel gelöscht. - Grund: Verdacht auf SPAM und den damit verbundenen verschwenderischen Umgang von wertvollen Bits und Bytes
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
2.809 Beiträge
 
Delphi 12 Athens
 
#5

AW: WM_POWERBROADCAST wie verwenden?

  Alt 30. Okt 2019, 20:38
Dann darf mal jemand von euch einen QP feature request
zur Aufnahme dieser WinAPI Funktionen schreiben. Ich tu's
nicht, da kenne ich mich ein wenig zu wenig aus und habe
außerdem eh' schon sehr viele QP reports

=> Freiwillige vor, damit das demnächst "out of the box" geht!

Grüße

TurboMagic
  Mit Zitat antworten Zitat
Benutzerbild von ULIK
ULIK

Registriert seit: 25. Sep 2006
Ort: Regensburg
416 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: WM_POWERBROADCAST wie verwenden?

  Alt 31. Okt 2019, 09:20
Hier mal eine etwas komplettere Unit
Delphi-Quellcode:
{-----------------------------------------------------------------------------
  Name:          uPowerManagement
  Author:        UK

  Description:
    Hilfsunit, die die Funktionen zum Registrieren der WM_POWERBROADCAST
    Messages bereitstellt (ab Win 8 nötig): dadurch empfängt diese BroadcastMessages
    für Suspend und Resume

    Aufruf erfolgt dann z.b. im FormCreate/Destroy mit dem Form-Handle, das die
    Message verarbeiten soll:


    procedure TForm1.FormCreate(Sender: TObject);
    begin
      RegisterPowermanagement(Handle);
    end;

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
      UnregisterPowermanagement;
    end;

  History:
    2019-10-30  UK  Unit created.
-----------------------------------------------------------------------------}


unit uPowerManagement;

interface

uses
  Winapi.Windows,
  System.SysUtils;

procedure RegisterPowermanagement(AMainForm: HWND);
procedure UnregisterPowermanagement;

implementation

var
  hLibrary: THandle = 0;
  hNotification: HPOWERNOTIFY = nil;

  RegisterSuspendResumeNotification: function(hRecipient: THandle; flags: DWORD): HPOWERNOTIFY; stdcall = nil;
  UnRegisterSuspendResumeNotification: function(hNotification: HPOWERNOTIFY): Bool; stdcall = nil;

{-----------------------------------------------------------------------------
  Procedure:  goIsWindows8OrHigher
  Author:      UK
  Description: Erkennung Windowsversion  (nur eine Möglichkeit)
  Arguments:
  Result:      Boolean
  Exceptions:  -
-----------------------------------------------------------------------------}


function goIsWindows8OrHigher: Boolean;
begin
  Result := ((Win32MajorVersion = 6) and (Win32MinorVersion >= 2)) or
             (Win32MajorVersion > 6);
end;
{-----------------------------------------------------------------------------
  Procedure:  RegisterPowermanagement
  Author:      UK
  Description:
  Arguments:  AMainForm : HWND - Fensterhandle Anwendung
  Result:      None
  Exceptions:  -
-----------------------------------------------------------------------------}


procedure RegisterPowermanagement(AMainForm: HWND);
begin
  if goIsWindows8OrHigher then // Erkennen, daß man unter Windows 8 und höher ist.
  begin
    if Assigned(RegisterSuspendResumeNotification) then
    begin
      hNotification := RegisterSuspendResumeNotification(AMainForm, DEVICE_NOTIFY_WINDOW_HANDLE);
      if hNotification <> nil then
        // Logging: SiUnit.LogString(lvDebug, 'Info', 'Powermanagement successfully registered')
      else
        ;// Logging: LogLastOSError('RegisterSuspendResumeNotification');
    end
    else
      ;// Logging: SiUnit.LogWarning('RegisterSuspendResumeNotification not registered');
  end;
end;

{-----------------------------------------------------------------------------
  Procedure:  UnregisterPowermanagement
  Author:      UK
  Description:
  Arguments:
  Result:      None
  Exceptions:  -
-----------------------------------------------------------------------------}


procedure UnregisterPowermanagement;
begin
  if goIsWindows8OrHigher then
  begin
    if Assigned(UnRegisterSuspendResumeNotification) then
    begin
      if (hNotification <> nil) then
      begin
        if UnRegisterSuspendResumeNotification(hNotification) then
          // Logging: SiUnit.LogString(lvDebug, 'Info', 'Powermanagement successfully unregistered')
        else
          // Logging: SiUnit.LogError('Failed to unregister notification: ' + LastWin32Error);
      end
      else
        // Logging: SiUnit.LogWarning('UnRegisterSuspendResumeNotification: no notification registered');
    end
    else
      // Logging: SiUnit.LogWarning('UnRegisterSuspendResumeNotification not registered');
  end;
end;

initialization

  hLibrary := LoadLibrary('user32.dll');
  if hLibrary <> 0 then
  begin
    RegisterSuspendResumeNotification := GetProcAddress(hLibrary, 'RegisterSuspendResumeNotification');
    UnRegisterSuspendResumeNotification := GetProcAddress(hLibrary, 'UnregisterSuspendResumeNotification');
  end;

finalization

  FreeLibrary(hLibrary);

end.
Ob man dafür jetzt einen QP Request schreiben sollte, bin ich mir nicht sicher. Es ist halt schon eine sehr spezielle Situation, daß man auf Suspend/Resume reagieren muß. Wenn dann sollte das jedenfalls in Winapi.Windows rein (da gibt's bereits ähnliche Deklarationen für das Powermanagement).
Aber das Ganze hier unter einem Vorbehalt: damit funktioniert es bei mir. Ob das aber nun wirklich der korrekte Weg ist, auf Suspend / Resume zu reagieren bin ich mir auch nicht 100% sicher. Dazu kenn ich mich zu wenig in dem Zeug aus.
Vieleicht können hier ja noch die Experten was beisteuern.

Geändert von ULIK (31. Okt 2019 um 09:42 Uhr) Grund: Korrektur kleiner Fehler
  Mit Zitat antworten Zitat
amigage

Registriert seit: 11. Nov 2005
Ort: Leipzig
270 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: WM_POWERBROADCAST wie verwenden?

  Alt 20. Dez 2019, 10:38
Hallo,

vielen Dank für den Thread. Dieser ist für mich sehr interessant, da ich mich aktuell auch mit dem Ermitteln von Ruhezustand und Erwachen beschäftige.
Mein Problem ist jedoch, dass ich kein Programm mit einem sichtbaren Fenster verwende, sondern einen Windows-Dienst. In dem Fall habe ich kein Handle des aktuellen Fensters.


Ich habe bereits im Netzt recherchiert und bin eigentlich nur auf "ist nicht möglich" gestoßen.
Aber es muss doch eine Möglichkeit geben, dass ein mit TService erstellter Dienst den Windows Ruhezustand ermitteln kann.

Über sachdienliche Hinweise würde ich mich freuen.

Gruß,
amigage
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
961 Beiträge
 
Delphi 6 Professional
 
#8

AW: WM_POWERBROADCAST wie verwenden?

  Alt 20. Dez 2019, 13:37
Hmm..

Was hindert dich daran per

AllocateHWnd

ein Fensterhandle zu holen und dies dann für die Aufrufe zu verwenden?

Ich habe einige nicht sichtbare Komponenten, welche so ohne 'Form' Windowsmessages erhalten und verarbeiten können..
(Ja ich Verwende Delphi 6 Pro und will NICHT wechseln!)
  Mit Zitat antworten Zitat
Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
717 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: WM_POWERBROADCAST wie verwenden?

  Alt 20. Dez 2019, 14:07
Danke für den Hinweis. Inzwischen bin ich auch schlauer: selbst
PBT_APMRESUMEAUTOMATIC
PBT_APMRESUMESUSPEND
PBT_APMSUSPEND
werden nicht empfangen.
Danke für deine Info. Aber: Ich verwende WM_POWERBROADCAST seit vielen Jahren in einem Onlinespiel ohne "RegisterSuspendResumeNotification" und es funktioniert auch im Insider Build Version 10.0.19041 (soeben getestet). Ich schliesse den Deckel, mein Programm empfängt WM_POWERBROADCAST wParam=PBT_APMSUSPEND. Ich öffne den Deckel und melde mich an und prüfe: Mein Programm empfängt zuerst PBT_APMRESUMESUSPEND und danach PBT_APMRESUMEAUTOMATIC. Dein Code aus #1 sollte also funktionieren.

Hast du eventuell bei der Deklaration message WM_POWERBROADCAST; vergessen (?).


Delphi-Quellcode:
type
  TMeinForm = class(TForm)
   ...
  procedure WMPowerBroadcast(var Msg: TMessage); message WM_POWERBROADCAST;


procedure TMeinForm.WMPowerBroadcast(var Msg: TMessage);
begin
  try
    case Msg.wParam of
    PBT_APMSUSPEND: ….
    PBT_APMRESUMESUSPEND: ….
    PBT_APMRESUMEAUTOMATIC: ….
Michael Gasser
  Mit Zitat antworten Zitat
Benutzerbild von ULIK
ULIK

Registriert seit: 25. Sep 2006
Ort: Regensburg
416 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: WM_POWERBROADCAST wie verwenden?

  Alt 20. Dez 2019, 15:34
Hallo,

Zitat:
Hast du eventuell bei der Deklaration message WM_POWERBROADCAST; vergessen (?).
das glaub ich nicht, denn PBT_APMPOWERSTATUSCHANGE ist ja durchgekommen. Im eigentlichen Programm war das auch schon mal alles funktionierend ohne das Register... eingebaut; ich bin darüber gestolpert, weil es auf einmal nicht mehr funktioniert hat. Entweder war das temporär bei Windows 10 deaktiviert und geht nun wieder oder es ist noch was anderes. Jedenfalls klappt's mit RegisterSuspendResumeNotification wieder


Frohe Weihnachten!
Uli
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:30 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