我在.Net 4.0中制作了一个屏幕保护程序。它基本上只是移动图像中的位并使用.Invalidate在计时器上显示它并覆盖onPaint事件。
到目前为止,它的效果很好 - 但是 - 我注意到它有一个问题。
暂停超时后停止监视器暂停。自从我安装它以来,我的显示器现在全天候停止。
问题是,我没有采取任何措施专门停止节电功能 - 而且我确保我的计算机的省电设置已经设置(它们是)。所以我选择了另一个屏幕保护程序,以确保设置仍然有效。监视器在超时后暂停。
我需要做些什么才能玩电源管理?我在Google上搜索了这个答案,我发现的一切都是如何阻止电源管理而我没有明确阻止它!我只想在适当的时候允许暂停。
答案 0 :(得分:1)
您是否偶然意外地捕获WM_SYSCOMMAND的0xF170(SC_MONITORPOWER)子命令?
答案 1 :(得分:1)
我能让我的节目“玩得很开心”。我不知道为什么这样做,原始代码没有,但这不仅有效 - 它实际上使程序更“省电”友好,因为它通过在屏幕暂停后不进行计算来减少CPU周期。简而言之,我预览WndProc消息并查看监视器正在被暂停消息,一旦收到消息,我将停止重绘直到它恢复(可以恢复并使屏幕保护程序仍处于活动状态)。
代码更改:
// Field Definitions
/// <summary>
/// Constants that relate to the WndProc messages we wish to intercept and evaluate.
/// </summary>
[System.Diagnostics.CodeAnalysis.SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:FieldNamesMustNotContainUnderscore", Justification = "Standard practice to use this naming style for Win32 API Constants.")]
private const int WM_SYSCOMMAND = 0x0112, SC_MONITORPOWER = 0xF170;
/// <summary>
/// Gets or sets whether we are suspended. Should coincide with whether the display is turned on or not.
/// </summary>
private bool isSuspended = false;
// New overridden method
/// <summary>
/// Intercepts WndProc messages. We are looking for the screen suspend activity. From it, we will return that we are able to suspend and we ourselves will suspend.
/// </summary>
/// <param name="m">Message to be checked.</param>
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_SYSCOMMAND)
{
// The 0x000F bits are used to indicate the specific state and must be ignored to see if this is a monitor power event.
if ((m.WParam.ToInt32() & 0xFFF0) == SC_MONITORPOWER)
{
switch (m.WParam.ToInt32() & 0x000F)
{
case -1:
// Display powering on - resume operation
#if DEBUG
System.Diagnostics.Debug.WriteLine("Display powered on.");
#endif
this.isSuspended = false;
break;
case 0:
case 1:
case 2:
// Display being powered off - suspend operation
#if DEBUG
System.Diagnostics.Debug.WriteLine("Display suspended");
#endif
this.isSuspended = true;
break;
default:
#if DEBUG
System.Diagnostics.Debug.WriteLine(string.Format("Unknown power state: {0}", (m.WParam.ToInt32() & 0x000F).ToString("0")));
#endif
// Assuming that unknown values mean to power off. This is a WAG.
this.isSuspended = true;
break;
}
}
}
base.WndProc(ref m);
}
// Change to my refreshing timer.
/// <summary>
/// Called when the refresh timer ticks. This invalidates the form, forcing it to be redrawn, which creates a framerate for us.
/// </summary>
/// <param name="sender">Who called this method.</param>
/// <param name="e">Event Arguments.</param>
private void RefreshTimer_Tick(object sender, EventArgs e)
{
if (this.isSuspended)
{
// Program is in suspended mode, so don't do anything this update.
return;
}
// Program is not suspended, so invalidate the client area so it can be painted again.
this.Invalidate();
}
进行此更改会在调用挂起时停止所有重绘(并停止GDI +计算),并且在完成此操作后,屏幕保护程序将“运行”并具有电源管理设置。