2016-12-16 22 views
1

我想做一個功能,如果用戶閒置一段時間,會超時並導航到主頁面。經過一番研究,我發現ThreadPoolTimer應該適合我的需求。測試它我決定使用10秒的時間間隔。如何檢查用戶是否在UWP上空閒?

timer =ThreadPoolTimer.CreatePeriodicTimer(Timer_Tick,TimeSpan.FromSeconds(10)); 

而這就是我無所適從的地方。我找不到一種方法來檢查UWP上的用戶輸入,而無需單獨檢查PointerPressed,PointerExited等。因此,我做了一些更深入的挖掘,並且發現了一段代碼,如果用戶想要給你一個布爾值閒置或不閒。

public static uint GetIdleTime() 
    { 
     LASTINPUTINFO lastInPut = new LASTINPUTINFO(); 
     lastInPut.cbSize = (uint)Marshal.SizeOf(lastInPut); 
     GetLastInputInfo(ref lastInPut); 

     return ((uint)Environment.TickCount - lastInPut.dwTime); 
    } 

    public static bool IsUserIdle() 
    { 
     uint idleTime = (uint)Environment.TickCount - GetLastInputEventTickCount(); 
     if (idleTime > 0) 
     { 
      idleTime = (idleTime/1000); 
     } 
     else 
     { 
      idleTime = 0; 
     } 
     //user is idle for 10 sec 
     bool b = (idleTime >= 10); 
     return b; 
    } 

    private static uint GetLastInputEventTickCount() 
    { 
     LASTINPUTINFO lii = new LASTINPUTINFO(); 
     lii.cbSize = (uint)Marshal.SizeOf(lii); 
     lii.dwTime = 0; 
     uint p = GetLastInputInfo(ref lii) ? lii.dwTime : 0; 
     return p; 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct LASTINPUTINFO 
    { 
     public static readonly int SizeOf = Marshal.SizeOf<LASTINPUTINFO>(); 
     [MarshalAs(UnmanagedType.U4)] 
     public UInt32 cbSize; 
     [MarshalAs(UnmanagedType.U4)] 
     public UInt32 dwTime; 
    } 

    [DllImport("user32.dll")] 
    private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); 

我然後調用打鉤功能的功能和使用條件語句如果IsUserIdle()等於真然後導航到主頁。

public static void Timer_Tick(object sender) 
    { 
     if (IsUserIdle() == true) 
     { 
      Frame.Navigate(typeof(MainPage)); 
     }           
    } 

但是,當我開始也沒有任何反應,之後我設置幾個斷點我發現IsUserIdle()從來沒有後閒置10秒返回真值。我完全卡住,所以任何幫助將不勝感激。

+0

對不起,我輸入得太快了。原始代碼應該是bool b =(idleTime> = 10); @gravity –

回答

2

GetLastInputInfo不支持Windows Store應用程序:

最低支持的客戶端:Windows 2000專業版[桌面應用程序只]

我不知道任何內在UWP API的來檢測用戶是否處於閒置狀態,但確實有可能掀起自己的機制。

我無法想出一個辦法來檢查一個UWP用戶輸入,而不必單獨檢查PointerPressed,PointerExited等

這有什麼不好說的方法嗎?這裏是我的嘗試:

App.xaml.cs

public sealed partial class App : Application 
{ 
    public static new App Current => (App)Application.Current; 

    public event EventHandler IsIdleChanged; 

    private DispatcherTimer idleTimer; 

    private bool isIdle; 
    public bool IsIdle 
    { 
     get 
     { 
      return isIdle; 
     } 

     private set 
     { 
      if (isIdle != value) 
      { 
       isIdle = value; 
       IsIdleChanged?.Invoke(this, EventArgs.Empty); 
      } 
     } 
    } 

    protected override void OnLaunched(LaunchActivatedEventArgs e) 
    { 
     idleTimer = new DispatcherTimer(); 
     idleTimer.Interval = TimeSpan.FromSeconds(10); // 10s idle delay 
     idleTimer.Tick += onIdleTimerTick; 
     Window.Current.CoreWindow.PointerMoved += onCoreWindowPointerMoved; 
    } 

    private void onIdleTimerTick(object sender, object e) 
    { 
     idleTimer.Stop(); 
     IsIdle = true; 
    } 

    private void onCoreWindowPointerMoved(CoreWindow sender, PointerEventArgs args) 
    { 
     idleTimer.Stop(); 
     idleTimer.Start(); 
     IsIdle = false; 
    } 
} 

MainPage.xaml.cs中

public sealed partial class MainPage : Page 
{ 
    protected override void OnNavigatedTo(NavigationEventArgs e) 
    { 
     App.Current.IsIdleChanged += onIsIdleChanged; 
    } 

    protected override void OnNavigatedFrom(NavigationEventArgs e) 
    { 
     App.Current.IsIdleChanged -= onIsIdleChanged; 
    } 

    private void onIsIdleChanged(object sender, EventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine($"IsIdle: {App.Current.IsIdle}"); 
    } 
} 

當指針已經沒有移動中10秒檢測空閒應用程序窗口。這也適用於只觸摸應用程序(如移動應用程序),因爲PointerMoved也會在點擊窗口時觸發。

+0

*「這種方法有什麼不好?」 - 簡而言之:它沒有提供。它只能記錄調用過程的輸入事件。它不區分用戶輸入和自動化結果的事件。這種方法既產生誤報也產生誤報,當然也不會確定用戶是否閒置。 – IInspectable

+0

不幸的是沒有其他選擇(我知道)。這對大多數場景來說已經足夠了。 –

+0

這可能會或可能不夠。然而,這個建議答案的讀者需要知道,這個實現在哪裏以及如何偏離基於'GetLastInputInfo'的解決方案。就目前而言,這個答案中甚至沒有提到任何區別。 – IInspectable