我用了幾個不同的技術捲起給我一個很好的解決方案解決了這個問題。我用GetLastInput摸出當系統最後一個接觸這很好記錄在其他地方,但這裏是我的方法:
public static class User32Interop
{
public static TimeSpan GetLastInput()
{
var plii = new LASTINPUTINFO();
plii.cbSize = (uint)Marshal.SizeOf(plii);
if (GetLastInputInfo(ref plii))
return TimeSpan.FromMilliseconds(Environment.TickCount - plii.dwTime);
else
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error());
}
[DllImport("user32.dll", SetLastError = true)]
static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
struct LASTINPUTINFO {
public uint cbSize;
public uint dwTime;
}
}
這只是告訴我,當系統處於空閒狀態,而不是應用程序。如果用戶點擊進入Word並在那裏工作一個小時,我仍然想要超時。爲了處理這種情況下,我只記得當我的應用程序通過重寫OnDeactivated失去焦點和OnActivated方法的適用對象:
override protected void OnDeactivated(EventArgs e)
{
this._lostFocusTime = DateTime.Now;
base.OnDeactivated(e);
}
protected override void OnActivated(EventArgs e)
{
this._lostFocusTime = null;
base.OnActivated(e);
}
我IsIdle程序添加到應用程序對象。它可以處理其中的應用程序具有焦點,但什麼都沒有發生(IsMachineIdle)全球情況和當用戶在做其他的東西(isAppIdle)的應用程序失去焦點的具體情況:
public bool IsIdle
{
get
{
TimeSpan activityThreshold = TimeSpan.FromMinutes(1);
TimeSpan machineIdle = Support.User32Interop.GetLastInput();
TimeSpan? appIdle = this._lostFocusTime == null ? null : (TimeSpan?)DateTime.Now.Subtract(_lostFocusTime.Value);
bool isMachineIdle = machineIdle > activityThreshold ;
bool isAppIdle = appIdle != null && appIdle > activityThreshold ;
return isMachineIdle || isAppIdle;
}
}
我做的最後一件事是創建一個定時器循環,幾秒鐘內輪詢該標誌事件。
這似乎工作正常。
請記住,_lostFocusTime應該聲明爲DateTime?變量。如果您試圖聲明爲DateTime,則不能將該值清空。 – Saren 2013-12-09 17:13:33
Environment.TickCount具有int類型,並且每24.9天被強制包裝。 LASTINPUTINFO.dwTime具有類型uint,所以它不會換到49.7天。如果機器運行時間超過24.9天,則示例中的數學問題被搞砸了。我通過調用WINAPI函數GetTickCount替換Environment.TickCount來緩解該問題,該函數也返回一個uint值。我不確定如果上次輸入的時間是49.5天,並且當前的滴答計數是50.0天,會發生什麼情況。 [根據另一個問題的這個答案](http://stackoverflow.com/a/1078089/2998072)它應該沒問題。 – 2016-11-02 00:50:27