You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何拦截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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 12:33:18