![]() |
WM_POWERBROADCAST wie verwenden?
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:
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.
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; 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 |
AW: WM_POWERBROADCAST wie verwenden?
Hmm
Lies mal hier zu PBT_APMQUERYSUSPEND: ![]() Zitat:
![]() 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... |
AW: WM_POWERBROADCAST wie verwenden?
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:
Der Aufruf erfolgt dann z.B. im FormCreate mit
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;
Delphi-Quellcode:
; entsprechend dann
hNotification := RegisterSuspendResumeNotification(Handle, DEVICE_NOTIFY_WINDOW_HANDLE);
Delphi-Quellcode:
im FormDestroy
UnRegisterSuspendResumeNotification(hNotification)
Frohes Schaffen! |
AW: WM_POWERBROADCAST wie verwenden?
Wo in die Delphi RTL würden diese fehlenden API Deklarationen rein gehören?
Macht es Sinn, einen QP Feature request dazu zu erfassen? |
AW: WM_POWERBROADCAST wie verwenden?
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 |
AW: WM_POWERBROADCAST wie verwenden?
Hier mal eine etwas komplettere Unit
Delphi-Quellcode:
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).
{-----------------------------------------------------------------------------
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. 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. :-) |
AW: WM_POWERBROADCAST wie verwenden?
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 |
AW: WM_POWERBROADCAST wie verwenden?
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.. |
AW: WM_POWERBROADCAST wie verwenden?
Zitat:
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: …. |
AW: WM_POWERBROADCAST wie verwenden?
Hallo,
Zitat:
Frohe Weihnachten! Uli |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:11 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