2016-12-16 23 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