C# Windows Forms应用无法检测系统睡眠/待机状态求助
解决Windows Forms中Modern Standby睡眠状态检测问题
针对你遇到的PowerModeChanged事件无法检测Modern Standby(Connected/Disconnected Standby)状态的问题,可以通过调用Windows原生Win32 API实现准确检测,该方案不依赖系统锁屏设置,兼容Windows 10及以后的现代设备(包括Surface平板)。
核心方案:注册电源设置通知并处理WM_POWERBROADCAST消息
通过PowerSettingRegisterNotificationAPI注册Modern Standby状态变化监听,并重写窗体的WndProc方法处理电源广播消息,直接捕获底层电源事件。
完整代码示例
using System; using System.Runtime.InteropServices; using System.Windows.Forms; using System.Diagnostics; public partial class MainForm : Form { // Win32消息与常量定义 private const int WM_POWERBROADCAST = 0x0218; private const int PBT_POWERSETTINGCHANGE = 0x8013; private const int PBT_APMSUSPEND = 0x0004; // 传统睡眠事件 private const int PBT_APMRESUMEAUTOMATIC = 0x0007; // 传统睡眠自动唤醒事件 // Modern Standby状态变化的GUID标识 private static readonly Guid GUID_CONNECTED_STANDBY_STATE_CHANGE = new Guid("98a7f580-01f7-48aa-9c0f-44352c29e5C0"); // Win32 API声明 [DllImport("user32.dll", SetLastError = true)] private static extern IntPtr PowerSettingRegisterNotification(IntPtr hWnd, ref Guid PowerSettingGuid, uint Flags); [DllImport("user32.dll", SetLastError = true)] private static extern bool PowerSettingUnregisterNotification(IntPtr Handle); private IntPtr _powerNotificationHandle; public MainForm() { InitializeComponent(); // 注册Modern Standby状态监听 _powerNotificationHandle = PowerSettingRegisterNotification(this.Handle, ref GUID_CONNECTED_STANDBY_STATE_CHANGE, 0); } protected override void WndProc(ref Message m) { base.WndProc(ref m); // 处理电源广播消息 if (m.Msg == WM_POWERBROADCAST) { switch (m.WParam.ToInt32()) { // 处理Modern Standby状态变化 case PBT_POWERSETTINGCHANGE: POWERBROADCAST_SETTING setting = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(m.LParam, typeof(POWERBROADCAST_SETTING)); if (setting.PowerSetting == GUID_CONNECTED_STANDBY_STATE_CHANGE) { int standbyState = Marshal.ReadInt32(setting.Data); if (standbyState == 1) { Trace.WriteLine("进入Modern Standby睡眠"); // 执行你的特定逻辑 } else if (standbyState == 0) { Trace.WriteLine("退出Modern Standby睡眠"); } } break; // 处理传统睡眠事件 case PBT_APMSUSPEND: Trace.WriteLine("进入传统睡眠"); // 执行你的特定逻辑 break; // 处理传统睡眠自动唤醒 case PBT_APMRESUMEAUTOMATIC: Trace.WriteLine("从传统睡眠自动唤醒"); break; } } } protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } // 注销电源监听,避免内存泄漏 if (_powerNotificationHandle != IntPtr.Zero) { PowerSettingUnregisterNotification(_powerNotificationHandle); } base.Dispose(disposing); } // 电源设置变化的结构体定义 [StructLayout(LayoutKind.Sequential, Pack = 4)] private struct POWERBROADCAST_SETTING { public Guid PowerSetting; public uint DataLength; public byte Data; } }
方案说明
- Modern Standby检测:通过注册
GUID_CONNECTED_STANDBY_STATE_CHANGE标识,捕获设备进入/退出Modern Standby的状态(1=进入,0=退出)。 - 传统睡眠兼容:同时处理
PBT_APMSUSPEND事件,覆盖传统Suspend睡眠场景,保证全设备兼容。 - 无依赖特性:直接监听底层电源事件,不依赖系统“睡眠时锁屏”的设置,稳定性更高。
内容的提问来源于stack exchange,提问作者Cameron Costa
相关产品推荐
相关产品推荐

