如何拦截Sleep按键按下操作并取消其触发的睡眠动作?
解决Sleep按键拦截后仍触发睡眠的问题
你的代码已经能捕获到VK_SLEEP按键消息,但系统仍进入睡眠,主要原因有两个:一是钩子逻辑存在疏漏,二是Sleep按键可能直接触发系统电源事件,需要额外拦截电源请求。
1. 修正键盘钩子逻辑
低级键盘钩子(WH_KEYBOARD_LL)要求当code < HC_ACTION时,必须调用CallNextHookEx而不能直接返回。你的代码缺少这个判断,可能导致部分系统逻辑绕过拦截。修正后的代码如下:
SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardMsgProc, hInstance, NULL); //... LRESULT WINAPI KeyboardMsgProc(int code, WPARAM wParam, LPARAM lParam) { // 仅当code合法时处理按键消息 if (code >= HC_ACTION) { KBDLLHOOKSTRUCT *kbhs = reinterpret_cast<KBDLLHOOKSTRUCT*>(lParam); if (kbhs->vkCode == VK_SLEEP) { OutputDebugStringA("VK_SLEEP catched\n"); // 返回非0值拦截按键消息 return 1; } } // 传递消息给下一个钩子 return CallNextHookEx(kb_hook, code, wParam, lParam); }
2. 拦截系统睡眠请求
部分键盘的Sleep键会直接触发ACPI电源事件,绕过键盘消息流程。此时需要在窗口过程中处理电源广播消息,阻止系统进入睡眠:
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_POWERBROADCAST: switch (wParam) { // 系统请求进入睡眠时,返回BROADCAST_QUERY_DENY阻止 case PBT_APMQUERYSUSPEND: OutputDebugStringA("Blocking system sleep request\n"); return BROADCAST_QUERY_DENY; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } // 其他窗口消息处理 default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } }
3. 确保程序权限
部分系统环境下,拦截电源事件需要管理员权限。右键程序选择“以管理员身份运行”,或者在程序清单中添加管理员权限声明,避免因权限不足导致拦截失效。
内容的提问来源于stack exchange,提问作者Ig_M
相关产品推荐
相关产品推荐

