WM_QUERYENDSESSION消息是Windows向你询问Windows能否关闭,WM_ENDSESSION消息表示提示你Windows即将关闭。故当应用程序退出时, WM_QUERYENDSESSION消息和WM_ENDSESSION消息均不响应。也就是说也就是说,你的程序在运行状态时,而系统由于某种原因需要注销或重启(或关机),此时操作系统会向你询问,但到你的同意(返回TRUE)后,系统才能做进一步的操作。


Windows 在注销、重起、关机之前会向每个当前正在运行的应用程序发送WM_QUERYENDSESSION消息,
--> 如果该应用程序方便关闭的话,则在此消息的消息响应函数OnQueryEndSession()中返回非0值(TRUE),否则返回0值(FALSE)。
--> 如果当前系统正在运行的应用程序全部返回非0值,则Windows的注销、重起、关机过程继续下去,并且向所有运行的应用程序发送WM_ENDSESSION消息,并且消息参数为TRUE;
--> 如果当前系统正在运行的应用程序其中之一返回0值,则Windows的注销、重起、关机过程被终止,并且不再继续对剩余的应用程序调用OnQueryEndSession()消息响应函数,而是向已经调用过了OnQueryEndSession()消息响应函数的应用程序发送WM_ENDSESSION消息,并且消息参数为FALSE。
所以一个应用程序只要响应WM_ENDSESSION消息,并在WM_ENDSESSION消息的消息响应函数OnEndSession(BOOL bEnding) 中根据参数bEnding来判断系统最后是否真的要注销、重起、关机了,然后做出适当的反应即可。
 
 
MSDN:

The framework calls this member function when the user chooses to end the Windows session or when an application calls theExitWindows Windows function. If any application returns 0, the Windows session is not ended. Windows stops callingOnQueryEndSession as soon as one application returns 0 and sends theWM_ENDSESSION message with a parameter value ofFALSE for any application that has already returned nonzero.

当用户选择关闭Windows或者应用程序调用Windows的ExitWindows函数时,框架调用这个成员函数。如果应用程序返回0,则Windows会话不会结束。只要有一个应用程序返回了0,Windows就停止调用OnQueryEndSession,并且向所有已经返回非零值的应用程序发送一个WM_ENDSESSION消息,参数值为FALSE。

目的:当用户注销系统的时候,注销前,让我的程序执行几行代码(释放资源/关闭端口之类的)。

思路:就跟把系统注销、重启和关机的消息都拦截下来,并销毁掉,不让其执行注销、重启和关机等操作原理是一样的。因为Windows在注销、重起、关机之前会向每个当前正在运行的应用程序广播一个消息WM_QUERYENDSESSION, 其lParam参数可以区分是关机还是注销用户(注销用户时lParam是ENDSESSION_LOGOFF)。然后Windows会等到所有的应用程序都对这个消息返回TRUE才会关机,因此,只要我们的应用程序对这个消息的处理返回FALSE,Windows就不会关机了。当系统注销的时候,所有非系统级的程序都会被退出,如果想让自己的程序在注销时仍然可以运行,就将自己的程序做成系统服务程序。

解决途径:拦截系统广播出来的WM_ENDSESSION和WM_QUERYENDSESSION消息。插一句:方法应该不止一种,比如系统钩子,但是参考网友的解决方案,程序一运行系统就奔溃了。没想到在MFC里面非常容易的通过重载WindowProc就可以实现,方法如下。

在MFC中的解决方法:

环境:VS 6.0, XP 32-bit

“查看”-->"建立类向导...",将WindowProc重载。

其函数体如下:

[cpp] view plain copy

  1. LRESULT CLabRelayDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
  2. {
  3. // TODO: Add your specialized code here and/or call the base class
  4. // WM_QUERYENDSESSION消息是Windows向你询问Windows能否关闭
  5. // WM_ENDSESSION消息表示提示你Windows即将关闭。
  6. switch(message) {
  7. case WM_ENDSESSION:
  8. // 把消息销毁掉,不让其正确转发。
  9. //message = WM_USERMESSAGE_NULL;
  10. //turn off the relay
  11. if(relayState==RELAY_ON)
  12. turnOff();
  13. break ;
  14. case WM_QUERYENDSESSION: //注销/关机
  15. //turn off the relay
  16. if(relayState==RELAY_ON)
  17. turnOff();
  18. break ;
  19. }
  20. return CDialog::WindowProc(message, wParam, lParam);
  21. }

就这样,系统注销的时候我的函数turnOff();被执行了。

关于lParam参数是通知码有一些的值:

ENDSESSION_CLOSEAPP 
0x00000001

The application is using a file that must be replaced, the system is being serviced, or system resources are exhausted. For more information, see Guidelines for Applications.

ENDSESSION_LOGOFF 
0x80000000

最新文章

  1. Android之仿ele地图定位效果
  2. 一次爬虫实践学习(C#)
  3. js禁止网页使用右键
  4. Linux IO模型和网络编程模型
  5. SQL Server 2008 数据库镜像部署实例之二 配置镜像,实施手动故障转移
  6. Android平台二维码之生成,扫描 & 识别
  7. Ubuntu-1404 GDB 调试C++报错
  8. kinect for windows sdk
  9. http协议了解
  10. timer的使用
  11. 【LeetCode】27 - Remove Element
  12. Java入门到精通——基础篇之多线程实现简单的PV操作的进程同步
  13. Android中获取应用程序(包)的信息----PackageManager
  14. 遍历map的四方方法
  15. java.lang.NoClassDefFoundError: Could not initialize class net.sf.json.util.JSONUtils
  16. Java+Python+Jython环境变量配置
  17. QSettings保存程序设置
  18. poj 3013 SPFA
  19. Django的信号机制
  20. Linux - 在Ubuntu下永久修改主机名

热门文章

  1. Sql Server的艺术(六) SQL 子查询,创建使用返回多行的子查询,子查询创建视图
  2. 07_Python变量内存地址、小数据池
  3. 解决axios传递参数后台无法接收问题
  4. My Calendar III
  5. Ubuntu14.04server + LNMP + Zabbix3.4安装教程
  6. JBOD
  7. Apache优化配置:修改最大并发连接数
  8. 洛谷 [p1196] 银河英雄传说
  9. Linux内存机制以及手动释放swap和内存
  10. vagrant系列教程(一):vagrant的安装与初识(转)