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

VS2010中笔记本无法接收PBT_APMSUSPEND消息,如何获取睡眠通知?

解决VS2010中笔记本睡眠事件捕获问题

一、修复WM_POWERBROADCAST消息失效问题

你的现有代码在笔记本上失效,大概率是以下原因及对应修复方案:

  1. 消息处理逻辑错误
    重点:你原代码中case WM_POWERBROADCAST的代码块末尾没有添加break,会导致该case执行完后继续进入default分支,这很可能是消息处理失效的核心原因! 修复后代码的WM_POWERBROADCASE分支需明确添加break。

  2. 系统现代待机/快速启动影响
    笔记本普遍启用现代待机(Modern Standby)或快速启动,传统的PBT_APMSUSPEND/PBT_APMRESUMEAUTOMATIC消息可能不会触发。需额外处理PBT_POWERSETTINGCHANGE事件,监测对应电源设置:

LRESULT Cttt1tDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_POWERBROADCAST:
    {
        switch (wParam)
        {
        case PBT_APMSUSPEND:
            MessageBox(_T("传统睡眠"));
            break;
        case PBT_APMRESUMEAUTOMATIC:
            MessageBox(_T("传统唤醒"));
            break;
        case PBT_POWERSETTINGCHANGE:
        {
            POWERBROADCAST_SETTING* pSetting = (POWERBROADCAST_SETTING*)lParam;
            // 监测现代待机(离开模式)状态
            if (IsEqualGUID(pSetting->PowerSetting, GUID_SYSTEM_AWAYMODE))
            {
                DWORD dwState = *(DWORD*)pSetting->Data;
                MessageBox(dwState == 1 ? _T("进入现代待机") : _T("退出现代待机"));
            }
            break;
        }
        default:
            break;
        }
        break; // 必须添加该break,避免逻辑混乱
    }
    default:
        break;
    }
    return CDialogEx::WindowProc(message, wParam, lParam);
}
  1. 窗口消息接收权限问题
    确保你的对话框是顶层窗口,没有被其他消息拦截函数(如PreTranslateMessage)误处理WM_POWERBROADCAST消息。

二、兼容VS2010的替代方法

如果WM_POWERBROADCAST仍无法满足需求,可使用以下兼容Windows Vista及以上、支持VS2010的方案:

1. PowerSettingRegisterNotification注册电源通知

该函数包含在VS2010默认的Windows 7 SDK中,无需升级VS:

#include <powrprof.h>
#pragma comment(lib, "powrprof.lib")

// 全局保存通知句柄
HPOWERNOTIFY g_hPowerNotify = NULL;

// 对话框初始化时注册通知
BOOL Cttt1tDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    g_hPowerNotify = PowerSettingRegisterNotification(
        m_hWnd,
        &GUID_SYSTEM_AWAYMODE,
        DEVICE_NOTIFY_WINDOW_HANDLE,
        NULL
    );

    if (!g_hPowerNotify)
    {
        MessageBox(_T("电源通知注册失败"));
    }

    return TRUE;
}

// 对话框销毁时取消注册
void Cttt1tDlg::OnDestroy()
{
    CDialogEx::OnDestroy();

    if (g_hPowerNotify)
    {
        PowerSettingUnregisterNotification(g_hPowerNotify);
        g_hPowerNotify = NULL;
    }
}

注册后,仍通过WM_POWERBROADCAST的PBT_POWERSETTINGCHANGE事件接收状态变更。

2. 旧版APM轮询方案(兼容Windows XP)

若需兼容更老系统,可通过定时器定期检查电源状态(效率较低,仅作备选):

// 定时器回调函数
VOID CALLBACK PowerStatusCheck(PVOID lpParam, BOOLEAN TimerFired)
{
    SYSTEM_POWER_STATUS sps;
    if (GetSystemPowerStatus(&sps))
    {
        // 0表示电池供电,可辅助判断睡眠前状态
        if (sps.ACLineStatus == 0)
        {
            MessageBox(_T("切换至电池供电,可能即将进入睡眠"));
        }
    }
}

// 初始化时创建定时器
HANDLE hPowerTimer = CreateWaitableTimer(NULL, TRUE, NULL);
LARGE_INTEGER liDueTime;
liDueTime.QuadPart = -10000000; // 1秒后启动,每隔1秒触发
SetWaitableTimer(hPowerTimer, &liDueTime, 1000, PowerStatusCheck, NULL, FALSE);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 14:50:37