一、实现思路
窗体中实现无操作,只需要监听鼠标和键盘操作即可。在窗体中加入定时器,每次鼠标或键盘操作重置定时器。
二、实现难点
1、监听鼠标、键盘的操作。我们新建类MyIMessageFilter继承IMessageFilter,实现PreFilterMessage方法。
(IMessageFilter的官方文档网址:键盘输入概述 - Windows Forms .NET | Microsoft Learn)
2、选择定时器(trime),这里选择System.Timers.Timer,System.Timers.Timer相较于System.Windows.Forms.Timer精度更高,可以处理更为复杂的操作。
3、其他线程中对UI线程进行操作(这里指计时结束方法中对窗体操作)。由于操作的线程不同,会产生线程安全的问题,c#中默认不允许的。解决方法有多种,本Dome中使用委托来实现。
三、Dome实现
1、在Visual Studio中新建Winform窗体程序(我这里选择.net)
2、新建类MyIMessageFilter
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public class MyIMessageFilter : IMessageFilter
{
//0x0200:鼠标移动
//0x0202:鼠标左键UP
//0x201:鼠标左键Down
//0x0203:鼠标左键双击
//0x0205:鼠标右键UP
//0x0204:鼠标右键Down
//0x020a:鼠标滚轮
//0x100:键盘按下
public bool PreFilterMessage(ref Message m)
{
//throw new NotImplementedException();
if (m.Msg == 0x0200 || m.Msg == 0x0202 || m.Msg == 0x0202 || m.Msg == 0x0203 || m.Msg == 0x0205 || m.Msg == 0x204 || m.Msg == 0x100)
{
System.Console.WriteLine("使用了鼠标和键盘");
if (Form1.timer != null)
{
Form1.timer.Stop();
Form1.timer.Start();
System.Console.WriteLine("定时器被重置");
}
}
return false;
}
}
}
3、在窗体中添加所需的控件(这里button1_Click去创建定时器)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public static System.Timers.Timer timer;
public Form1()
{
InitializeComponent();
panel1.Show();
panel2.Hide();
//开启监听键盘和鼠标操作
Application.AddMessageFilter(new MyIMessageFilter());
}
//达到时间间隔发生的方法
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
//throw new NotImplementedException();
//关闭定时器,并释放内存
timer.Stop();
timer.Dispose();
timer = null;
Invoke((MethodInvoker) delegate{
panel1.Show();
panel2.Hide();
label1.Text = "已经有5s未操作";
MessageBox.Show("定时器已经关闭");
});
}
//下一页
private void button1_Click(object sender, EventArgs e)
{
panel1.Hide();
panel2.Show();
//这里用按钮创建定时器,等同于登录等操作
//创建定时器
timer = new System.Timers.Timer();
//定时器达到时间触发的事件
timer.Elapsed += Timer_Elapsed;
//是否触发Timer_Elapsed事件,为true才能触发
timer.Enabled = true;
//间隔时间(单位为毫秒)
timer.Interval = 5000;
//打开定时器
timer.Start();
}
private void button2_Click(object sender, EventArgs e)
{
panel1.Show();
panel2.Hide();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (timer!=null)
{
//关闭定时器,并释放资源
timer.Stop();
timer.Dispose();
timer = null;
}
}
}
}
4、操作前
5、点击下一页后
6、无操作等待5秒后
四、总结
1、本方法是对整个程序进行监听键盘和鼠标,即使跳转新的Form也能够实现监听(注:必须是同一窗体程序中才能实现)。
2、定时器中添加的方法和窗体不是同一线程,由于C# 的机制,默认不允许跨线程操作。
3、虽然C#有和Java相同的垃圾回收机制,但为了避免定时器未关闭就结束进程的问题。这里用窗体的FormClosing事假来判断定时器是否关闭。(注:FormClosing表示窗体关闭前的回调事件,本Dome手动释放资源,托管对象实际会自动释放资源)。