【问题标题】:How to check if user is idle on UWP? [duplicate]如何检查用户在 UWP 上是否空闲? [复制]
【发布时间】:2016-12-16 15:30:24
【问题描述】:

我想创建一个功能,如果用户空闲一段时间,它会超时并导航到主页。经过一番研究,我发现 ThreadPoolTimer 应该适合我的需要。测试它我决定使用 10 秒的间隔。

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

然后我在 tick 函数中调用该函数,如果 IsUserIdle() 等于 true,则使用条件语句然后导航到主页。

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

但是当我启动它时,什么也没有发生,并且在我设置了几个断点之后,我发现 IsUserIdle() 即使在 10 秒不活动之后也永远不会返回真值。我完全被卡住了,所以任何帮助都将不胜感激。

【问题讨论】:

  • 对不起,我打字太快了。原始代码应该是 bool b = (idleTime >= 10); @重力

标签: c# timer uwp


【解决方案1】:

GetLastInputInfo 不支持 Windows 应用商店应用:

支持的最低客户端:Windows 2000 Professional [仅限桌面应用程序]

我不知道有任何内在的 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 也会在点击窗口时触发。

【讨论】:

  • “这种方法有什么不好?” - 简而言之:它没有实现。它只能记录调用进程的输入事件。而且它不区分用户输入和自动化结果的事件。这种方法会产生误报和漏报,当然不能确定用户是否处于空闲状态。
  • 不幸的是,别无选择(我知道)。这对于大多数情况来说已经足够了。
  • 这可能够也可能不够。但是,此建议答案的读者需要知道,此实现在何处以及如何偏离基于GetLastInputInfo 的解决方案。就目前而言,这个答案中的任何内容都没有暗示任何差异。
  • 我实际上已经通过使用调度程序计时器和滴答函数而不是线程池计时器解决了我最初的问题。它在我调试时完美运行,但现在当我尝试在发布模式下运行它时,我得到一个 System.TypeLoad 异常,指出程序集中的未解析 P/Invoke 方法“GetLastInputInfo!user32.dll”,因为它在 UWP 应用程序中不可用。请使用另一个 API 或使用 [DllImport(ExactSpelling=true) 来表明您了解使用非 UWP 应用程序 API 的含义。 @IInspectable
  • 报告。建议的答案在 UWP windows IOT 上非常稳定。赞成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-07
  • 1970-01-01
  • 1970-01-01
  • 2011-02-16
  • 1970-01-01
  • 2011-11-27
  • 1970-01-01
相关资源
最近更新 更多