Windows如何决定显示屏幕保护程序

时间:2012-06-10 17:12:49

标签: c# windows winapi screensaver

Windows有一个内部机制,通过检查用户交互性和其他任务(某人正在观看视频等)来决定何时显示屏幕保护程序(或关闭屏幕)。

是否有一个Win API允许我询问用户是否处于活动状态,或者他们上次何时处于活动状态?

2 个答案:

答案 0 :(得分:6)

它被称为“空闲计时器”。你可以通过调整CallNtPowerInformation()来获取它的价值,询问SystemPowerInformation。返回的SYSTEM_POWER_INFORMATION.TimeRemaining字段告诉您空闲计时器剩余多少时间。 SystemExecutionState请求告诉您是否有任何线程调用SetThreadExecutionState()来停止计时器,就像显示视频的应用程序所做的那样。

using System;
using System.Runtime.InteropServices;

public static class PowerInfo {
    public static int GetIdleTimeRemaining() {
        var info = new SYSTEM_POWER_INFORMATION();
        int ret = GetSystemPowerInformation(SystemPowerInformation, IntPtr.Zero, 0, out info, Marshal.SizeOf(info));
        if (ret != 0) throw new System.ComponentModel.Win32Exception(ret);
        return info.TimeRemaining;
    }

    public static int GetExecutionState() {
        int state = 0;
        int ret = GetSystemExecutionState(SystemExecutionState, IntPtr.Zero, 0, out state, 4);
        if (ret != 0) throw new System.ComponentModel.Win32Exception(ret);
        return state;
    }

    private struct SYSTEM_POWER_INFORMATION {
        public int MaxIdlenessAllowed;
        public int Idleness;
        public int TimeRemaining;
        public byte CoolingMode;
    }
    private const int SystemPowerInformation = 12;
    private const int SystemExecutionState = 16;
    [DllImport("powrprof.dll", EntryPoint = "CallNtPowerInformation", CharSet = CharSet.Auto)]
    private static extern int GetSystemPowerInformation(int level, IntPtr inpbuf, int inpbuflen, out SYSTEM_POWER_INFORMATION info, int outbuflen);
    [DllImport("powrprof.dll", EntryPoint = "CallNtPowerInformation", CharSet = CharSet.Auto)]
    private static extern int GetSystemExecutionState(int level, IntPtr inpbuf, int inpbuflen, out int state, int outbuflen);

}

答案 1 :(得分:0)

你应该看看GetLastInputInfo函数,该函数返回一个结构,其中包含上次用户输入的滴答计数,一个滴答为1ms。然后,您可以通过Environment.TickCount将其与值returend进行比较,以获得自上次用户输入以来经过的时间(以毫秒为单位)。

此功能的P / Invoke定义可在此处获取:http://www.pinvoke.net/default.aspx/user32.GetLastInputInfo

请注意,GetLastInputInfo返回的刻度值在短短50天内回归到零,但Environment.TickCount包裹的时间不到25天,因为{{1}返回的值作为unsigned int,并且TickCount被签名。在大多数情况下,这可能不是一个大问题,但值得记住的是,偶尔会有一些奇怪的行为,大约每月一次。