我用这段代码来拦截键盘Sleep按钮向下和向上的动作:
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);
}
按钮按下被拦截(这被记录)。但电脑仍然进入睡眠模式。
那么如何拦截睡眠按钮按下并取消其动作呢?
不幸的是,这里没有人回答我的问题。但我尝试了很多不同的功能和方法等。我还发现低级键盘钩子在电脑开始进入睡眠模式后捕获消息
VK_SLEEP
。所以处理它没有意义。
例如,RemyLebeau 注意到的
SetThreadExecutionState()
功能将仅在内部系统计时器到期时阻止 PC 进入睡眠模式。
并且处理
WM_POWERBROADCAST
和 WM_QUERYENDSESSION
消息也没有取消按下键盘 Sleep 按钮后 PC 进入睡眠模式。
所以我的问题的解决方案是使用电源管理功能:
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;
取消键盘睡眠按钮操作:
if(PowerWriteACValueIndex(NULL, pDuplicateActivePowerScheme, &GUID_SLEEPBUTTON_ACTION, &PowerSettingGuid, 0) != ERROR_SUCCESS)//0 - prevent action
return false;
if(PowerSetActiveScheme(NULL, pDuplicateActivePowerScheme) != ERROR_SUCCESS)
return false;
当不再需要取消操作时:
//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;
}
这也可用于取消按下键盘电源按钮的操作。它适用于 Vista 及更高版本(我还没有在 XP 上测试过)。为了方便起见,我编写了自己的类来禁用电源按钮的操作。请记住,此代码不会阻止“开始”菜单 ->“关闭/睡眠”操作(我没有问过)。感谢PJ Arends的文章,帮助我解决了我的问题。