using System; using System.Runtime.InteropServices; using System.Threading; namespace Utils { /// /// 空闲监控工具 /// 提供定时器操作方法,当用户超过指定时间未操作时,触发Timeout事件 /// public class IdleUtil { #region Public /// /// 重置定时器为新时间 /// /// 超过多少时间未操作发出事件(毫秒) public void Reset(int dueTime) { Start(dueTime); } /// /// 重置定时器 /// public void Reset() { Start(this.DueTime); } /// /// 开始计时 /// /// 超过多少时间未操作发出事件(毫秒) public void Start(int dueTime) { DueTime = dueTime; if (!IsRunning) { IsRunning = true; MonitorThread = new Thread(Moniter) { IsBackground = true }; MonitorThread.Start(); } Timer.Change(dueTime, Timeout.Infinite); } /// /// 停止计时 /// public void Stop() { IsRunning = false; Timer.Change(Timeout.Infinite, Timeout.Infinite); } #endregion Public #region Event /// /// 超过指定事件未操作事件 /// public event EventHandler TimeoutEvent; #endregion Event #region Ctor public IdleUtil() { Timer = new Timer(OnTimeout); } #endregion Ctor #region Private /// /// 定时器 /// private readonly Timer Timer; /// /// 用户要求定时时间 /// private int DueTime; /// /// 线程是否运行 /// private bool IsRunning; /// /// 监控线程 /// private Thread MonitorThread; /// /// 监控线程方法 /// private void Moniter() { while (IsRunning) { if (GetLastInputTime() == 0) Reset(); Thread.Sleep(1000); } } #endregion Private #region Trigger private void OnTimeout(object _) { if (TimeoutEvent != null) TimeoutEvent(this, EventArgs.Empty); // 只触发一次 Timer.Change(Timeout.Infinite, Timeout.Infinite); } #endregion Trigger #region WindowsAPI [DllImport("user32.dll")] private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii); /// /// 获取用户最后一次输入的时间 /// /// 最后一次输入的时间 private static uint GetLastInputTime() { uint idleTime = 0; LASTINPUTINFO lastInputInfo = new LASTINPUTINFO(); lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo); lastInputInfo.dwTime = 0; uint envTicks = (uint)Environment.TickCount; if (GetLastInputInfo(ref lastInputInfo)) { uint lastInputTick = lastInputInfo.dwTime; idleTime = envTicks - lastInputTick; } return ((idleTime > 0) ? (idleTime / 1000) : 0); } [StructLayout(LayoutKind.Sequential)] private struct LASTINPUTINFO { public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO)); [MarshalAs(UnmanagedType.U4)] public UInt32 cbSize; [MarshalAs(UnmanagedType.U4)] public UInt32 dwTime; } #endregion WindowsAPI } }