2011.12.11整理
烛秋
一、网络上流传的方法
网络上流传的方法很多,也很复杂。之前在实现这个功能的时候在网络上寻找了很多,如下:
http://blog.csdn.net/rainharder/article/details/6101317
http://topic.csdn.net/t/20021009/15/1081843.html#r_7006146
http://topic.csdn.net/u/20100414/12/A5265E43-6288-43A0-B337-C5DA0CF1D7DD.html#r_64661983
http://topic.csdn.net/u/20100203/12/6B7E7AF7-D5DA-4BA5-A6EF-8A38866B4C1B.html#r_63377844
http://topic.csdn.net/u/20080603/17/5EBACC7D-5F96-4A29-AD7C-55FD8F47CD45.html
http://topic.csdn.net/u/20100203/12/6b7e7af7-d5da-4ba5-a6ef-8a38866b4c1b.html
一些代码试了之后发现很多并没有实现功能。譬如下面的代码:
static UINT dss_GetList[] = { SPI_GETLOWPOWERTIMEOUT, SPI_GETPOWEROFFTIMEOUT, SPI_GETSCREENSAVETIMEOUT }; static UINT dss_SetList[] = { SPI_SETLOWPOWERTIMEOUT, SPI_SETPOWEROFFTIMEOUT, SPI_SETSCREENSAVETIMEOUT }; m_pValue = new int[dss_ListCount]; for (int x = 0; x < dss_ListCount; x++) { SystemParametersInfo(dss_GetList[x], 0, &m_pValue[x], 0); SystemParametersInfo(dss_SetList[x], 0, NULL, 0); } 和 for (int x = 0; x<dss_ListCount; x++) { SystemParametersInfo(dss_SetList[x], m_pValue[x], NULL, 0); }
上边的代码可以在很多地方看到,但在xp\win7下都没有效果。这些无效的代码到处黏贴,误人不浅。
二、通过测试确定可行的代码
去掉屏保:
bool bAct; ::SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, &bAct, 0); if (bAct) { ::SystemParametersInfo(SPI_SETSCREENSAVEACTIVE, false, 0, 0); }
恢复屏保:
if ( bAct ) { ::SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, true, 0, 0 ); }
取消电源管理,避免睡眠、待机:
::SetThreadExecutionState( ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED );
恢复电源管理:
::SetThreadExecutionState( ES_CONTINUOUS );
三、附上解决这一问题时的记录
2011.10.24
2011.10.25
一、解决屏保问题的解决方式有两种:
1、可以通过SystemParametersInfo(SPI_SETSCREENSAVEACTIVE,FALSE,NULL,0);实现。
2、通过在处理WM_SYSCOMMAND消息,当wParam参数为:SC_SCREENSAVE时,处理该消息,返回true。要注意的是,这种方式的局限性:只有当前的Activate窗口,才能收到这个进入屏保的消息!
二、解决的电源管理的解决方式有三种:
1、 通过SystemParamerinfo设置,参数为 SPI_SETLOWPOWERTIMEOUT和SPI_SETPOWEROFFTIMEOUT。但有时候不灵,如在xp、win7下都不行。这个方法是网络上的,实地测试之后,发现不靠谱!!
2、不关闭显示器的解决方式:通过处理WM_SYSCOMMAND消息,当wParam参数为:SC_MONITORPOWER时。这个方式的局限性跟上边的一样,可能无法收到该消息。
3、使用定时器调用SetThreadExecutionState函数,可以使得系统不关闭显示器、不睡眠。
三、具体实现:
1、干掉屏保:SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, false, 0, 0);
获取屏保设置:SystemParametersInfo( SPI_GETSCREENSAVEACTIVE, 0, &m_bSCreenSave, 0 );
恢复屏保设置:SystemParametersInfo( SPI_SETSCREENSAVEACTIVE, m_bSCreenSave, 0, 0);
2、干掉电源管理:
设置定时器:SetTimer(1, 5000);
定时调用:SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
2011.10.26
四、具体实现修正
不需要定时调用SetThreadExecutionState,只需要参数加上ES_CONTINUOUS即可。
SetThreadExecutionState( ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED );
用完之后:SetThreadExecutionState( ES_CONTINUOUS );
ES_CONTINUOUS参数的作用是“冻结”空闲计数器,直到下一次调用
参考资料:http://msdn.microsoft.com/en-us/library/ms995870.aspx
Calling the SetThreadExecutionState function without the ES_CONTINUOUS flag will simply reset the idle timers and the system will go to sleep if the timers run out again. To keep the system or the display awake it may be necessary to use the ES_CONTINUOUS flag along with either the ES_SYSTEM_REQUIRED or the ES_DISPLAY_REQUIRED flag. This will freeze the respective timers. If the ES_CONTINUOUS flag is used in conjunction with ES_DISPLAY_REQUIRED or ES_SYSTEM_REQUIRED, applications should then release the idle timers by resending just the ES_CONTINUOUS flag when there is no longer a need to prevent them from timing out.
四、相关问题
1、屏幕保护在注册表中的位置:HKEY_CURRENT_USER\Control Panel\Desktop
2、电影管理相关:HKEY_CURRENT_USER\Control Panel\PowerCf
3、发现注册表里修改了屏保时间,并没有生效。
4、睡眠跟待机不同,睡眠需要重新按开机键。
5、笔记本的电源管理。联想的笔记本有电源管理设置用于关闭屏幕背光,几分钟无操作之后,笔记本屏幕就变黑,但这个时候系统没有待机、没有睡眠、没有屏保。怎么让它不关闭背光呢?查找了很久,感觉这是无法解决的问题,它不属于电源管理,可能是硬件级别上的实现。