最近的案子需要程式去偵測suspend resume
那這樣就要搞清楚測試機台的預設sleep模式是 S3 還是modern standby
因為偵測的方法不同
S3的方法我用的是 ↓
SystemEvents.PowerModeChanged += OnPowerChange;
private void OnPowerChange(object s, PowerModeChangedEventArgs e)
{
switch (e.Mode)
{
case PowerModes.Resume:
break;
case PowerModes.Suspend:
break;
}
}
*此法在modern standby機台無效
也就是sleep模式採用modern standby的機台
PowerChange的Event不會被Trigger
-----------------------------------------------------------------------
測試機台的sleep模式是採用modern standby
Modern Standby的方法我用的是 ↓
public MainWindow()
{ ...
this.SourceInitialized += MainWindow_SourceInitialized;
...
}
void MainWindow_SourceInitialized(object sender, EventArgs e)
{
RegisterSuspendResumeNotification();
IntPtr hwnd = new WindowInteropHelper(this).Handle;
HwndSource.FromHwnd(hwnd).AddHook(new HwndSourceHook(WndProc));
}
IntPtr hSLEEPRESUME
[DllImport(@"User32", SetLastError = true, EntryPoint = "RegisterSuspendResumeNotification", CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr RegisterSuspendResumeNotification(IntPtr hRecipient, Int32 Flags);
private void RegisterSuspendResumeNotification()
{
IntPtr handle = new WindowInteropHelper(System.Windows.Application.Current.Windows[0]).Handle;
hSLEEPRESUME=RegisterSuspendResumeNotification(handle, DEVICE_NOTIFY_WINDOW_HANDLE);
}
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_POWERBROADCAST:
OnPowerBroadcast(wParam, lParam);
break;
default:
break;
}
return IntPtr.Zero;
}
private void OnPowerBroadcast(IntPtr wParam, IntPtr lParam)
{
if ((int)wParam == PBT_APMSUSPEND)//系統暫停執行
;
else if ((int)wParam == PBT_APMRESUMEAUTOMATIC) //喚醒
;
else if ((int)wParam == PBT_APMRESUMESUSPEND)//喚醒
;
}
* 以下文字截自Windows休眠与唤醒事件
如果系统自动起来(非人为点击操作),会发送PBT_APMRESUMEAUTOMATIC事件
如果系统因人为唤醒(鼠标、键盘、电源键),会先发送PBT_APMRESUMEAUTOMATIC事件,再发送PBT_APMRESUMESUSPEND事件(休眠唤醒事件),同时系统点亮屏幕。这时你的程序需要重新打开因为系统睡眠时关闭的文件。
-----------------------------------------------------------------------
補充:節電模式開始與關閉的提醒
Windows桌面應用現在可以在節電模式開始與關閉時進行提醒。
通過改變節能模式,應用也可以在續航方面做出一定貢獻。
GUID_POWER_SAVING_STATUS:此全新GUID與RegisterPowerSettingNotification即可實現通知功能。
原文網址:Win10桌面/手機版最深層次開發功能挖掘 https://kknews.cc/tech/n36z5o5.html
程式實作:
public MainWindow()
{ ...
this.SourceInitialized += MainWindow_SourceInitialized;
...
}
void MainWindow_SourceInitialized(object sender, EventArgs e)
{
RegisterForPowerNotifications();
IntPtr hwnd = new WindowInteropHelper(this).Handle;
HwndSource.FromHwnd(hwnd).AddHook(new HwndSourceHook(WndProc));
}
IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case WM_POWERBROADCAST:
OnPowerBroadcast(wParam, lParam);
break;
default:
break;
}
return IntPtr.Zero;
}
Guid GUID_POWER_SAVING_STATUS = new Guid(0xE00958C0, 0xC213, 0x4ACE, 0xAC, 0x77, 0xFE, 0xCC, 0xED, 0x2E, 0xEE, 0xA5);
const int DEVICE_NOTIFY_WINDOW_HANDLE = 0x00000000;
IntPtr hBATTERYSAVERCHANGE
private void RegisterForPowerNotifications()
{
IntPtr handle = new WindowInteropHelper(System.Windows.Application.Current.Windows[0]).Handle;
hBATTERYSAVERCHANGE = RegisterPowerSettingNotification(handle, ref GUID_POWER_SAVING_STATUS, DEVICE_NOTIFY_WINDOW_HANDLE);
}
internal struct POWERBROADCAST_SETTING
{
public Guid PowerSetting;
public uint DataLength;
public byte Data;
}
const int PBT_POWERSETTINGCHANGE = 0x8013;
private void OnPowerBroadcast(IntPtr wParam, IntPtr lParam)
{
if ((int)wParam == PBT_POWERSETTINGCHANGE)
{
POWERBROADCAST_SETTING ps = (POWERBROADCAST_SETTING)Marshal.PtrToStructure(lParam, typeof(POWERBROADCAST_SETTING));
if (ps.PowerSetting == GUID_POWER_SAVING_STATUS)
{
if (ps.Data == 0)
{
Console.WriteLine("Disable Battery Saver Mode");
IsBatSaver = false;
}
else if (ps.Data == 1)
{
Console.WriteLine("Enable Battery Saver Mode");
IsBatSaver = true;
}
}
}
-----------------------------------------------------------------------
*根據一起合作此案的bios team engineer所說
bios設定選單可以選要用S3 或 modern standby 進sleep
所以看起來兩者不會共存
後記:
因為我需要在機台resume的時候do something
所以雖說客戶機台預設的模式是modern standby
但為了保險起見
我的程式裡還是同時放了判斷S3 跟 modern standby suspend resume的程式碼
參考資料