I use this code to intercept the keyboard Sleep button down and up action:
SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardMsgProc, hInstance, NULL);
//...
LRESULT WINAPI KeyboardMsgProc(int code, WPARAM wParam, LPARAM lParam)
{
KBDLLHOOKSTRUCT *kbhs = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam);
if(kbhs->vkCode == VK_SLEEP)
{
OutputDebugStringA("VK_SLEEP catched\r\n");
return 1;//deny button action
}
return CallNextHookEx(kb_hook, code, wParam, lParam);
}
The button press is intercepted (this is logged). But the computer still goes into sleep mode.
So how to intercept the sleep button press and cancel its action?
Unfortunately, no one here has given an answer to my question. But I tried many different functions and methods etc. I also found out that the low-level keyboard hook catches message VK_SLEEP
after the PC starts to go into sleep mode. So there's no point in processing it.
For example, the SetThreadExecutionState()
function noticed by RemyLebeau will prevent the PC from going into sleep mode only when the internal system timer expires.
And processing WM_POWERBROADCAST
and WM_QUERYENDSESSION
messages also didn't cancel the PC’s entering to sleep mode after the keyboard Sleep button pressed.
So the solution to my question is to use the power management functions: PowerGetActiveScheme()
, PowerWriteACValueIndex()
, PowerSetActiveScheme()
:
//init - receive the original power scheme, preserve it and duplicate it for further usage
pDuplicateActivePowerScheme = NULL;
pCurrentActivePowerScheme = NULL;
if(PowerGetActiveScheme(NULL, &pCurrentActivePowerScheme) != ERROR_SUCCESS)
return;
if(PowerDuplicateScheme(NULL, pCurrentActivePowerScheme, &pDuplicateActivePowerScheme) != ERROR_SUCCESS)
return;
Cancel the keyboard Sleep button action:
if(PowerWriteACValueIndex(NULL, pDuplicateActivePowerScheme, &GUID_SLEEPBUTTON_ACTION, &PowerSettingGuid, 0) != ERROR_SUCCESS)//0 - prevent action
return false;
if(PowerSetActiveScheme(NULL, pDuplicateActivePowerScheme) != ERROR_SUCCESS)
return false;
When the action is no longer required to be cancelled:
//cleanup and restore the original power scheme
if(pCurrentActivePowerScheme != NULL)
{
if(PowerSetActiveScheme(NULL, pCurrentActivePowerScheme) == ERROR_SUCCESS)
{
if(pDuplicateActivePowerScheme != NULL)
{
PowerDeleteScheme(NULL, pDuplicateActivePowerScheme);
LocalFree(pDuplicateActivePowerScheme);
pDuplicateActivePowerScheme = NULL;
}
}
LocalFree(pCurrentActivePowerScheme);
pCurrentActivePowerScheme = NULL;
}
This can also be used to cancel the action of the keyboard Power button press. It works on Vista and higher (I haven't tested it on XP). For convenience, I wrote my own class to disable the actions of the power buttons. Keep in mind that this code does not prevent Start menu -> Shut down / Sleep action (I didn't ask that). Thanks to PJ Arends for his article, which helped me to solve my question.