我需要计算我的
WPF应用程序的空闲时间(空闲时间=没有键盘输入,鼠标输入(运动点击)发生).
到目前为止,我尝试了两种方法,但是似乎没有任何一种方法:
到目前为止,我尝试了两种方法,但是似乎没有任何一种方法:
>每次获取contextIdle优先级时,使用调度程序调用委托,问题是绑定和许多其他操作调用它,因此我无法真正使用它.
>使用我注册到“System.Windows.Input.InputManager.Current.PostProcessInput”事件的输入管理器,每次被调用时,我重新启动空闲时间计数.
第二种方法看起来很有希望,但是问题是当鼠标在应用程序上(它有焦点)时,我不断得到事件.
解决方法
我用几种不同的技术解决了这个问题,为我提供了一个很好的解决方案.当系统上次触摸时,我使用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; } }
我做的最后一件事是创建一个定时器循环,轮询这个标志事件几秒钟.
这似乎工作正常.