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

如何用Qt C++实现Windows笔记本睡眠/休眠的程序化通知?

问题分析与解决方案

问题背景

基于Windows 11 Pro笔记本开发的Qt应用,使用WM_POWERBROADCAST事件监听系统睡眠/休眠状态时,手动触发睡眠(合盖或电源菜单操作)无法收到PBT_APMSUSPEND事件,但台式机上运行正常;仅当系统睡眠过夜后开机(从启动阶段恢复)时能收到该事件。

核心原因

Windows 11笔记本默认启用**Modern Standby(S0低功耗空闲)**模式,而非传统的S3睡眠模式:

  • 传统S3睡眠模式下,系统会发送PBT_APMSUSPEND事件
  • Modern Standby模式下,系统进入低功耗状态但不会触发PBT_APMSUSPEND,仅在真正进入休眠(如长时间睡眠触发的S4)时才会发送该事件,这就是过夜睡眠后能收到消息的原因

此外需确认原有代码是否正确注册事件过滤器(若未注册也会导致事件无法捕获):

// 在main函数中添加事件过滤器注册逻辑
MyEventFilter filter;
QAbstractEventDispatcher::instance()->installNativeEventFilter(&filter);

解决方案:使用RegisterSuspendResumeNotification

RegisterSuspendResumeNotification是Windows 8及以上提供的API,兼容传统睡眠和Modern Standby模式,能可靠捕获系统挂起/恢复事件。以下是Qt环境下的实现步骤:

1. 实现通知处理器类

创建类封装电源通知的注册、回调和注销逻辑:

头文件(PowerNotificationHandler.h)

#include <QObject>
#include <windows.h>

class PowerNotificationHandler : public QObject
{
    Q_OBJECT
public:
    explicit PowerNotificationHandler(QObject *parent = nullptr);
    ~PowerNotificationHandler();

private:
    static VOID CALLBACK PowerSettingCallback(
        PVOID Context,
        ULONG Type,
        PVOID Setting
    );

    HANDLE m_notificationHandle = nullptr;
};

源文件(PowerNotificationHandler.cpp)

#include "PowerNotificationHandler.h"
#include <QDebug>

PowerNotificationHandler::PowerNotificationHandler(QObject *parent)
    : QObject(parent)
{
    // 注册挂起/恢复通知,使用回调模式
    m_notificationHandle = RegisterSuspendResumeNotification(
        this,
        DEVICE_NOTIFY_CALLBACK
    );

    if (m_notificationHandle == nullptr) {
        qDebug() << "注册电源通知失败,错误码:" << GetLastError();
    }
}

PowerNotificationHandler::~PowerNotificationHandler()
{
    // 注销通知,避免资源泄漏
    if (m_notificationHandle != nullptr) {
        UnregisterSuspendResumeNotification(m_notificationHandle);
        m_notificationHandle = nullptr;
    }
}

// 电源事件回调函数
VOID CALLBACK PowerNotificationHandler::PowerSettingCallback(
    PVOID Context,
    ULONG Type,
    PVOID Setting
)
{
    PowerNotificationHandler* handler = static_cast<PowerNotificationHandler*>(Context);
    if (!handler) return;

    switch (Type) {
    case PBT_APMSUSPEND:
        qDebug() << "系统即将进入睡眠/休眠";
        break;
    case PBT_APMRESUMEAUTOMATIC:
        qDebug() << "系统自动恢复(如定时唤醒)";
        break;
    case PBT_APMRESUMESUSPEND:
        qDebug() << "用户手动唤醒系统";
        break;
    default:
        qDebug() << "未知电源事件类型:" << Type;
        break;
    }
}

2. 在应用中启用处理器

在main函数中实例化该类,确保其生命周期与应用一致:

#include <QApplication>
#include "PowerNotificationHandler.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    // 初始化电源通知处理器
    PowerNotificationHandler powerHandler;

    // 启动你的主窗口
    // MainWindow w;
    // w.show();

    return a.exec();
}

3. 验证电源模式(可选)

可通过命令行查看当前系统支持的睡眠模式:
打开管理员权限的命令提示符,执行:

powercfg /a

若输出包含“待机 (S0 低功耗空闲) 网络连接”或“待机 (S0 低功耗空闲) 断开网络”,说明系统使用Modern Standby模式,此时必须使用RegisterSuspendResumeNotification才能捕获睡眠事件。


内容的提问来源于stack exchange,提问作者Qt Beginner

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 10:25:45