I've been working on wrapping the full WM_POWERBROADCAST
Windows Message, and encapsulating it inside of an event driven component. A majority of it is working fine, and I have also further captured all of the PBT_POWERSETTINGCHANGE
setting GUID's - except for one GUID_POWERSCHEME_PERSONALITY
.
According to the docs, I am supposed to translate the Data
member to a TGUID
...
The active power scheme personality has changed. All power schemes map to one of these personalities. The Data member is a GUID that indicates the new active power scheme personality.
The problem is with the data type provided is as follows:
Data: packed array[0..0] of UCHAR;
How do I acquire a TGUID
out of this Data
member?
Here's how I am currently capturing the rest of these settings, upon capturing the PBT_POWERSETTINGCHANGE
event...
procedure TPowerMonitor.HandlePowerSetting(const Val: PPowerBroadcastSetting);
var
VDWord: DWORD;
function IsVal(G: String): Boolean;
begin
Result:= Assigned(Val);
if Result then
Result:= IsEqualGUID(StringToGUID(G), Val.PowerSetting);
end;
begin
if IsVal('{5d3e9a59-e9D5-4b00-a6bd-ff34ff516548}') then begin
//GUID_ACDC_POWER_SOURCE
VDWord:= DWORD(Val.Data[0]);
if Assigned(Self.FOnSourceChange) then
FOnSourceChange(Self, TPowerSource(VDWord));
end else
if IsVal('{a7ad8041-b45a-4cae-87a3-eecbb468a9e1}') then begin
//GUID_BATTERY_PERCENTAGE_REMAINING
VDWord:= DWORD(Val.Data[0]);
if Assigned(Self.FOnBatteryPercent) then
FOnBatteryPercent(Self, VDWord);
end else
if IsVal('{6fe69556-704a-47a0-8f24-c28d936fda47}') then begin
//GUID_CONSOLE_DISPLAY_STATE
VDWord:= DWORD(Val.Data[0]);
if Assigned(FOnConsoleDisplayState) then
FOnConsoleDisplayState(Self, TPowerDisplayState(VDWord));
end else
if IsVal('{786E8A1D-B427-4344-9207-09E70BDCBEA9}') then begin
//GUID_GLOBAL_USER_PRESENCE
VDWord:= DWORD(Val.Data[0]);
if Assigned(FOnGlobalUserPresence) then
FOnGlobalUserPresence(Self, TPowerUserPresence(VDWord));
end else
if IsVal('{515c31d8-f734-163d-a0fd-11a08c91e8f1}') then begin
//GUID_IDLE_BACKGROUND_TASK
if Assigned(FOnIdleBackgroundTask) then
FOnIdleBackgroundTask(Self);
end else
if IsVal('{02731015-4510-4526-99e6-e5a17ebd1aea}') then begin
//GUID_MONITOR_POWER_ON
VDWord:= DWORD(Val.Data[0]);
if Assigned(FOnMonitorPower) then
FOnMonitorPower(Self, TPowerDisplayState(VDWord));
end else
if IsVal('{E00958C0-C213-4ACE-AC77-FECCED2EEEA5}') then begin
//GUID_POWER_SAVING_STATUS
VDWord:= DWORD(Val.Data[0]);
if Assigned(FOnPowerSavingStatus) then
FOnPowerSavingStatus(Self, TPowerSavingStatus(VDWord));
end else
if IsVal('{245d8541-3943-4422-b025-13A784F679B7}') then begin
//GUID_POWERSCHEME_PERSONALITY
//TODO: How to read "Data" as a TGUID?
//GUID_MIN_POWER_SAVINGS (8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c)
//GUID_MAX_POWER_SAVINGS (a1841308-3541-4fab-bc81-f71556f20b4a)
//GUID_TYPICAL_POWER_SAVINGS (381b4222-f694-41f0-9685-ff5bb260df2e)
end else
if IsVal('{2B84C20E-AD23-4ddf-93DB-05FFBD7EFCA5}') then begin
//GUID_SESSION_DISPLAY_STATUS
VDWord:= DWORD(Val.Data[0]);
if Assigned(FOnSessionDisplayState) then
FOnSessionDisplayState(Self, TPowerDisplayState(VDWord));
end else
if IsVal('{3C0F4548-C03F-4c4d-B9F2-237EDE686376}') then begin
//GUID_SESSION_USER_PRESENCE
VDWord:= DWORD(Val.Data[0]);
if Assigned(FOnSessionUserPresence) then
FOnSessionUserPresence(Self, TPowerUserPresence(VDWord));
end else
if IsVal('{98a7f580-01f7-48aa-9c0f-44352c29e5C0}') then begin
//GUID_SYSTEM_AWAYMODE
VDWord:= DWORD(Val.Data[0]);
if Assigned(FOnAwayMode) then
FOnAwayMode(Self, TPowerAwayMode(VDWord));
end else begin
//Unrecognized GUID
//TODO: Handle error
end;
end;
This is documented here:
POWERBROADCAST_SETTING structure
The struct is what is know as a "variable length structure". The final member is, potentially, longer than actually declared. The DataLength
member tells you how much data is actually present in the Data
member. For example, you can read it out with a call to System.Move()
.
If the payload really is a GUID then check that DataLength
is the size of a GUID and copy the data into your GUID variable.
var
GUID: TGUID;
....
// check that DataLength = SizeOf(TGUID)
Move(Data, GUID, DataLength);
The data for other power scheme GUIDs is typically a DWORD
, which is handled in an analogous fashion.