我需要计算我的WPF应用程序的空闲时间(空闲时间=没有键盘输入,鼠标输入(移动+点击))。 到目前为止,我尝试了两种方法,但似乎没有一种方法可以工作:
还有其他想法吗?或者可能是修改第二种解决方案的方法吗?
答案 0 :(得分:13)
我用一些不同的技术解决了这个问题,为我提供了一个很好的解决方案。我使用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;
}
}
我做的最后一件事是创建一个定时器循环,在几秒钟内轮询此标志事件。
这似乎工作正常。
答案 1 :(得分:5)
好吧没有人回答所以我继续挖掘并找到一个相对简单的解决方案,使用操作系统最后输入+运行时间。代码非常简单但是这个解决方案让我进行数据轮询,这是我从不推荐的,而且不是在应用程序级别,而是在操作系统级别,这不是我需要的确切解决方案。 如果有人打开这个帖子这就是代码,只需使用GetIdleTime():
public class IdleTimeService
{
//Importing the Dll & declaring the necessary function
[DllImport("user32.dll")]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
/// <summary>
/// return the current idle time (in ms)
/// </summary>
/// <returns>current idle time in ms</returns>
public static int GetIdleTime()
{
//Creating the object of the structure
LASTINPUTINFO lastone = new LASTINPUTINFO();
//Initialising
lastone.cbSize = (uint)Marshal.SizeOf(lastone);
lastone.dwTime = 0;
int idleTime = 0;
//To get the total time after starting the system.
int tickCount = System.Environment.TickCount;
//Calling the dll function and getting the last input time.
if (GetLastInputInfo(ref lastone))
{
idleTime = tickCount - (int)lastone.dwTime;
return idleTime;
}
else
return 0;
}
}