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