2012-06-10 39 views
1

Windows有一個內部機制,通過檢查用戶交互性和其他任務(某人正在觀看視頻等)來決定何時顯示屏幕保護程序(或關閉屏幕)。Windows如何決定顯示屏幕保護

是否有一個Win API允許我詢問用戶是否處於活動狀態,或者他們上次何時處於活動狀態?

回答

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); 

} 
+0

pinvoke網站不提供SYSTEM_POWER_INFORMATION c#實現和我的似乎產生無效值。你能否請你用示例實現更新你的答案? – sternr

+0

感謝那正是我正在尋找 – sternr

0

您應該看看GetLastInputInfo函數,它返回一個包含上次用戶輸入的滴答計數的結構,一個滴答是1ms。然後,您可以將此值與的值相比較,以獲取自上次用戶輸入以來的經過時間(以毫秒爲單位)。

AP/Invoke的定義此功能,請點擊這裏:http://www.pinvoke.net/default.aspx/user32.GetLastInputInfo

要知道,雖然,該刻度值由GetLastInputInfo包裹返回到零隻是短期的50天,但Environment.TickCount包裝只是短期的25天,由於GetLastInputInfo返回的值是一個無符號整數,並且TickCount被簽名。在大多數情況下,這可能不是什麼大問題,但值得記住的是,偶爾會有一些奇怪的行爲,每月一次。

+0

GetLastInputInfo很棒,但它並不考慮作爲活動報告的應用程序。例如 - 當您在Media Player中觀看電影時,只要電影正在播放,您將無法進入屏幕保護程序,但GetLastInputInfo將不會顯示 – sternr

+0

某些阻止屏幕保護程序的應用程序似乎是通過響應Windows消息('WM_SYSCOMMAND'與'SC_SCREENSAVE'的'wParam'),而不是讓默認處理程序執行它。我想不出從OS以外使用這種機制的好方法。 –

相關問題