diff --git a/IdleUtil/IdleUtil.cs b/IdleUtil/IdleUtil.cs new file mode 100644 index 0000000..0e1e573 --- /dev/null +++ b/IdleUtil/IdleUtil.cs @@ -0,0 +1,167 @@ +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 + } +} \ No newline at end of file