uses Windows, CommCtrl;
type
PPOWERBROADCAST_SETTING = ^POWERBROADCAST_SETTING;
POWERBROADCAST_SETTING = record
PowerSetting: GUID;
DataLength: DWORD;
Data: array[0..0] of UCHAR;
end;
const
GUID_CONSOLE_DISPLAY_STATE: TGuid = '{6FE69556-704A-47A0-8F24-C28D936FDA47}';
GUID_MONITOR_POWER_ON: TGuid = '{02731015-4510-4526-99E6-E5A17EBD1AEA}';
CSomeSubclassId = 1;
function NewWndProc(Wnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM; uISubClass: UINT_PTR; dwRefData: DWORD_PTR): LRESULT; stdcall;
var
Form: TForm1 absolute dwRefData;
procedure LogEvent(const Event: string);
begin
Form.Memo1.Append(Event + ' at ' + DateTimeToStr(Now));
end;
const
WM_POWERBROADCAST = 536;
PBT_POWERSETTINGCHANGE = 32787;
var
Event: PPOWERBROADCAST_SETTING absolute lParam;
begin
case uMsg of
WM_SYSCOMMAND:
if wParam and $FFF0 = SC_SCREENSAVE then
LogEvent('Screen saver started');
WM_POWERBROADCAST:
if (wParam = PBT_POWERSETTINGCHANGE)
and (IsEqualGUID(Event^.PowerSetting, GUID_CONSOLE_DISPLAY_STATE)
or IsEqualGUID(Event^.PowerSetting, GUID_MONITOR_POWER_ON)) then
begin
case Event^.Data[0] of
0:
LogEvent('The monitor is off');
1:
LogEvent('The monitor is on');
2:
LogEvent('The monitor is dimmed');
end;
end;
end;
Result := DefSubclassProc(Wnd, uMsg, wParam, lParam);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
RegisterPowerHook;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
UnregisterPowerHook;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
UnregisterPowerHook;
end;
function RegisterPowerSettingNotification(hRecipient: THandle; PowerSettingGuid: PGuid; Flags: DWORD): Pointer; stdcall; external User32;
function UnregisterPowerSettingNotification(Handle: Pointer): BOOL; stdcall; external User32;
procedure TForm1.RegisterPowerHook;
const
DEVICE_NOTIFY_WINDOW_HANDLE = 0;
begin
if not Assigned(PNewRegStateInfo) then
PNewRegStateInfo := RegisterPowerSettingNotification(Handle, @GUID_CONSOLE_DISPLAY_STATE, DEVICE_NOTIFY_WINDOW_HANDLE);
if not Assigned(PNewRegStateInfo) then // check PNewRegStateInfo not POldRegStateInfo
POldRegStateInfo := RegisterPowerSettingNotification(Handle, @GUID_MONITOR_POWER_ON, DEVICE_NOTIFY_WINDOW_HANDLE);
SetWindowSubclass(Handle, @NewWndProc, CSomeSubclassId, DWORD_PTR(Self));
end;
procedure TForm1.UnregisterPowerHook;
begin
RemoveWindowSubclass(Handle, @NewWndProc, CSomeSubclassId);
if Assigned(PNewRegStateInfo) then
begin
UnregisterPowerSettingNotification(PNewRegStateInfo);
PNewRegStateInfo := nil;
end;
if Assigned(POldRegStateInfo) then
begin
UnregisterPowerSettingNotification(POldRegStateInfo);
POldRegStateInfo := nil;
end;
end;