Win32 响应windows系统睡眠/休眠和重启/关机/注销的消息
(这里以win7为例,xp、win8/win10类似)
1.睡眠/休眠
windows系统默认显示睡眠,休眠是不显示的,如下图所示:
如果要调出休眠选项,可在控制面板中选择电源选项->更改计划设置->更改高级电源选项,到下图
关闭混合睡眠,设置休眠时间,保存后即可显示休眠,如下图,
所谓的混合睡眠,就是睡眠和休眠混合在一起,如果想感受其中的差别,可以自己点击分别感受下:
睡眠:关闭混合睡眠和休眠,点击睡眠按钮,即可进入睡眠模式,多次点击鼠标或键盘即可恢复
休眠:关闭混合睡眠,点击休眠按钮,即可进入休眠模式,只能通过按压开机按钮才能恢复
混合睡眠:打开混合睡眠,点击睡眠,即可进入混合睡眠模式,多次点击鼠标或键盘即可恢复
注意:xp系统显示的是待机/休眠,win7/win8/win10则显示的是睡眠/休眠
2.消息响应
(WindowProc与DefWindowProc的区别是前面用来处理自定义的窗口的消息,而后面是windows系统默认处理的消息,所以应该重载WindowProc
通过MFC查看WindowProc源码,可看到函数里面未处理的消息会调用DefWindowProc)
1)睡眠/休眠
睡眠/休眠响应的消息是一样的,都是PBT_APMSUSPEND,恢复的时候是PBT_APMRESUMEAUTOMATIC,而对于PBT_APMQUERYSUSPEND这个消息测试的时候发现收不到,所以程序中没有用
LRESULT CDlg***::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch (message)
{
case WM_POWERBROADCAST:
{
switch(wParam)
{
case PBT_APMSUSPEND: //睡眠、休眠
{
....
}
break;
case PBT_APMRESUMEAUTOMATIC: //睡眠、休眠恢复
{
....
}
break;
}
}
break;
}
return CDialogEx::WindowProc(message, wParam, lParam);
}
经验证从xp到win10所有系统,都能响应到消息
如何像暴风影音那样,播放视频的时候禁止系统自动睡眠,播放完了再恢复呢?
利用SetThreadExecutionState这个api函数即可
播放视频时:
::SetThreadExecutionState( ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED );
停止播放时:
::SetThreadExecutionState( ES_CONTINUOUS );
2.重启/关机/注销
重启/关机/注销都是系统向应用程序发送一个消息WM_QUERYENDSESSION,确定关闭时再发送一个WM_ENDSESSION,其中通过lParam可以区分是注销(ENDSESSION_LOGOFF),还是重启/关机(注意:无法区分是重启还是关机)
原理:
LRESULT CDlg****::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
switch (message)
{
case WM_QUERYENDSESSION: //关机、重启、注销
{
if (lParam == ENDSESSION_LOGOFF)//注销
{
....
}
else //重启/关机
{
....
}
}
break;
}
return CDialogEx::WindowProc(message, wParam, lParam);
}
说明:
(1)经验证DefWindowProc中响应不到该消息WM_QUERYENDSESSION的,只有WindowProc中才能响应到
(2)下面是从xp到win10系统响应消息时的wParam,lParam值,仅供参考,
xp:重启、管家,wpara、lpawa都是0, 注销:lParam:-2147483648,wpara:0
win7:重启、管家,wpara、lpawa都是0, 注销:lParam:-2147483648,wpara:0
win8:重启、管家,wpara、lpawa都是0, 注销:lParam:-2147483648,wpara:0
win10有的与上面一样,有的则是下面的值
部分win10:
重启:lParam:1073741824,wpara:0
管家:lParam:1073741824,wpara:0
注销:lParam:-2147483648,wpara:0
可以看出注销时lParam都是一样的,而重启/关机时值有些不同
(3)能阻止系统重启或关机吗?
网上有说在响应WM_QUERYENDSESSION中通过返回FALSE来禁止系统重启/关机,经验证从xp到win10,有的系统可以,而有的系统不管返回值是TRUE还是FALSE,WM_ENDSESSION接受到的关机参数都是TRUE,即会直接重启/关机,所以是无法兼容所有系统做到阻止系统重启或关机的
(4)设置重启/关机/注销时程序退出顺序
当系统发生上述行为时,可以设置程序不是最先被退出的,防止用户点击取消重启/关机/注销
//设置系统重启、关闭、注销时程序关闭顺序
SetProcessShutdownParameters(0x100, SHUTDOWN_NORETRY);
可自行网上搜索这个api,注意第一个参数如果设置为0,会导致系统在重启/关机/注销的画面已经出来后应用程序仍然显示的情况,参考第一个参数的范围合理设置值即可
注意(纯属个人理解):应用程序一般通过WM_QUERYENDSESSION和SetProcessShutdownParameters来处理程序防止假重启/关机/注销的情况,而不是直接响应WM_ENDSESSION进行处理,个人感觉响应WM_QUERYENDSESSION留给程序处理的时间更多一些。