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
}
}