C# 当用户空闲或不活动时,如何在Windows应用程序中设置计时器
在Windows窗体中,我有一个关于在用户空闲或不活动时设置计时器的问题。我需要定时器设置任何鼠标事件。如果用户做出任何时刻,那么我需要重置计时器。这就是要求。代码在这里C# 当用户空闲或不活动时,如何在Windows应用程序中设置计时器,c#,.net,winforms,timer,C#,.net,Winforms,Timer,在Windows窗体中,我有一个关于在用户空闲或不活动时设置计时器的问题。我需要定时器设置任何鼠标事件。如果用户做出任何时刻,那么我需要重置计时器。这就是要求。代码在这里 using System; using System.Windows.Forms; using Timer = System.Windows.Forms.Timer; namespace FormsTimerSetup.Globals { public class SetApplicationTimeOut : Fo
using System;
using System.Windows.Forms;
using Timer = System.Windows.Forms.Timer;
namespace FormsTimerSetup.Globals
{
public class SetApplicationTimeOut : Form
{
#region
/// <summary>
/// Private Timer Property
/// </summary>
private static Timer _timer;
/// <summary>
/// Timer Property
/// </summary>
public static Timer Timer
{
get
{
return _timer;
}
set
{
if (_timer != null)
{
_timer.Tick -= Timer_Tick;
}
_timer = value;
if (_timer != null)
{
_timer.Tick += Timer_Tick;
}
}
}
#endregion
#region Events
public event EventHandler UserActivity;
#endregion
#region Constructor
/// <summary>
/// Default/Parameterless SetApplicationTimeOut Constructor
/// </summary>
public SetApplicationTimeOut()
{
KeyPreview = true;
FormClosed += ObservedForm_FormClosed;
MouseMove += ObservedForm_MouseMove;
KeyDown += ObservedForm_KeyDown;
}
#endregion
#region Inherited Methods
/// <summary>
///
/// </summary>
/// <param name="e"></param>
protected virtual void OnUserActivity(EventArgs e)
{
// Invoking the UserActivity delegate
UserActivity?.Invoke(this, e);
}
/// <summary>
///
/// </summary>
public void SetTimeOut()
{
// postpone auto-logout by 30 minutes
_timer = new Timer
{
Interval = (30 * 60 * 1000) // Timer set for 30 minutes
};
Application.Idle += Application_Idle;
_timer.Tick += new EventHandler(Timer_Tick);
}
#endregion
#region Private Methods
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ObservedForm_MouseMove(object sender, MouseEventArgs e)
{
OnUserActivity(e);
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ObservedForm_KeyDown(object sender, KeyEventArgs e)
{
OnUserActivity(e);
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ObservedForm_FormClosed(object sender, FormClosedEventArgs e)
{
FormClosed -= ObservedForm_FormClosed;
MouseMove -= ObservedForm_MouseMove;
KeyDown -= ObservedForm_KeyDown;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void Application_Idle(object sender, EventArgs e)
{
_timer.Stop();
_timer.Start();
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void Timer_Tick(object sender, EventArgs e)
{
_timer.Stop();
Application.Idle -= Application_Idle;
MessageBox.Show("Application Terminating");
Application.Exit();
}
#endregion
}
}
使用系统;
使用System.Windows.Forms;
使用Timer=System.Windows.Forms.Timer;
命名空间FormsTimerSetup.Globals
{
公共类SetApplicationTimeOut:表单
{
#区域
///
///专用计时器属性
///
专用静态定时器_定时器;
///
///计时器属性
///
公共静态定时器
{
得到
{
返回定时器;
}
设置
{
如果(_timer!=null)
{
_timer.Tick-=定时器_Tick;
}
_定时器=值;
如果(_timer!=null)
{
_timer.Tick+=定时器_Tick;
}
}
}
#端区
#地区活动
公共事件事件处理程序用户活动;
#端区
#区域构造函数
///
///默认/无参数SetApplicationTimeOut构造函数
///
public SetApplicationTimeOut()
{
KeyPreview=true;
FormClosed+=观察到的Form_FormClosed;
MouseMove+=观察到的形式\u MouseMove;
KeyDown+=观察到的形式u KeyDown;
}
#端区
#区域继承方法
///
///
///
///
受保护的虚拟void OnUserActivity(EventArgs e)
{
//调用UserActivity委托
UserActivity?调用(this,e);
}
///
///
///
公共void SetTimeOut()
{
//将自动注销延迟30分钟
_定时器=新定时器
{
间隔=(30*60*1000)//计时器设置为30分钟
};
Application.Idle+=应用程序\u Idle;
_timer.Tick+=新事件处理程序(timer\u Tick);
}
#端区
#区域私有方法
///
///
///
///
///
private void observed form_MouseMove(对象发送方,MouseEventArgs e)
{
主动性(e);
}
///
///
///
///
///
私有void ObservedForm_KeyDown(对象发送方,KeyEventArgs e)
{
主动性(e);
}
///
///
///
///
///
私有void ObservedForm_FormClosed(对象发送方,FormClosedEventArgs e)
{
FormClosed-=观察到的Form_FormClosed;
MouseMove-=观察到的形式\u MouseMove;
KeyDown-=观察到的形式u KeyDown;
}
///
///
///
///
///
私有静态无效应用程序\u空闲(对象发送方、事件参数)
{
_timer.Stop();
_timer.Start();
}
///
///
///
///
///
私有静态无效计时器(对象发送器、事件参数)
{
_timer.Stop();
Application.Idle-=应用程序\u Idle;
MessageBox.Show(“应用程序终止”);
Application.Exit();
}
#端区
}
}
我已经实现了代码,但不确定它是否是正确的方法
任何潜在客户都将不胜感激。我不会深入了解您的代码,但我想直接解决这个问题。 我认为在这种情况下,“环岛”会起作用 例如,您可以在鼠标移动时进行检查,并将其与初始位置进行比较 在上面添加初始化组件() 然后添加以下内容:
void gmh_TheMouseMoved()
{
if(XY==false)
{
MouseX = Convert.ToInt32(Cursor.Position.X);
MouseY = Convert.ToInt32(Cursor.Position.Y);
}
else
{
MouseX1 = Convert.ToInt32(Cursor.Position.X);
MouseY1 = Convert.ToInt32(Cursor.Position.Y);
XY = true;
if(MouseX1==MouseX && MouseY1==MouseY)
{
if(yourTimerNameHere.Enabled==false)
{
yourTimerNameHere.Start();
}
}
else
{
yourTimerNameHere.Stop();
yourTimerNameHere.Start();
}
}
}
将其添加到表单的类之外:
public delegate void MouseMovedEvent();
public class GlobalMouseHandler : IMessageFilter
{
private const int WM_MOUSEMOVE = 0x0200;
public event MouseMovedEvent TheMouseMoved;
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_MOUSEMOVE)
{
if (TheMouseMoved != null)
{
TheMouseMoved();
}
}
return false;
}
}
接下来创建4个int,分别命名为MouseX=0、MouseY=0、MouseX1=0和MouseY1=0以及bool XY=false
所以实际上,每当光标移动时,位置就会被记录下来,并与下一个位置进行比较。因此,您可以检查鼠标是否空闲
请注意,我还没有测试这段代码,所以请随时回复任何错误
问:“我需要定时器设置任何鼠标事件…如果用户进行任何移动,那么我需要重置定时器…任何线索将不胜感激。”
我会尽量提供一些线索,希望对你有用。您说希望MouseMove事件重置计时器,但有一个问题:每当子控件有焦点时,都是子控件接收鼠标事件,而主窗体没有。这是可以解决的
简短的回答是:“在主窗口类上实现IMessageFilter接口,以便在检测到鼠标移动时重置计时器。”添加MessageFilter可以在鼠标消息发送到焦点控件之前拦截鼠标消息
因此,现在我必须向您提供所有详细信息,下面是一个很长的答案:它首先向我们的主表单1添加IMessageFilter接口,如下所示:
public partial class Form1 : Form, IMessageFilter
IMessageFilter要求我们的类只实现一个方法:
public bool PreFilterMessage(ref Message m)
{
switch (m.Msg)
{
case WM_MOUSEMOVE:
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// Commit f9367d7c added at OP's request
case WM_KEYDOWN:
// This makes WakeUp persist if user is typing in the textbox.
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TimeOutState = TimeOutState.WakeUp;
break;
}
return false; // Do not suppress downstream message
}
const int // WinOS Messages
WM_KEYDOWN = 0x0100,
WM_MOUSEMOVE = 0x0200;
您可以看到,现在任何鼠标移动都会将我们的应用程序的TimeOutState设置回“唤醒”
enum TimeOutState{ WakeUp, Sleeping, Warning, Exit }
我们只需要一个计时器,计时器的每一个滴答声间隔(这里设置为5秒)将减少一个状态。如果鼠标不移动,它会一直递减,最后退出
下面是运行应用程序60秒的60秒。您可以看到每5秒或鼠标移动时发生的更改。如果您想运行该示例,可以从我们的GitHub repo获得最新提交
以下是其余的详细信息:
enum TimeOutState{ WakeUp, Sleeping, Warning, Exit }
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
// When our main window is ready for messages, add the MessageFilter
Application.AddMessageFilter(this);
// ...and start the timer for the first time.
TimeOutState = TimeOutState.WakeUp;
}
public Form1()
{
InitializeComponent();
_wdt = new Timer();
_wdt.Interval = 5000; // Use a very short time-out for this demo
_wdt.Tick += _wdt_Tick;
}
Timer _wdt; // Watch-Dog Timer
private void _wdt_Tick(object sender, System.EventArgs e)
{
// A tick reduces the TimeOutState by 1
TimeOutState = (TimeOutState)(TimeOutState - 1);
}
TimeOutState TimeOutState
{
get => _timeOutState;
set
{
switch (value)
{
case TimeOutState.WakeUp:
_wdt.Stop();
_wdt.Start();
break;
case TimeOutState.Exit:
_wdt.Stop();
Application.Exit();
return;
}
if (value != _timeOutState) // If state changes, write message
{
Debug.WriteLine(value.ToString(), _timeOutState.ToString());
// In a timer callback that changes the UI, it's
// best to post the action in the message queue.
BeginInvoke((MethodInvoker)delegate
{
textBox1.AppendText(_timeOutState.ToString());
if (TimeOutState == TimeOutState.Warning)
{
textBox1.AppendText(
": Closing in " + (_wdt.Interval / 1000).ToString() + " seconds.");
}
textBox1.AppendText(Environment.NewLine);
textBox1.Select(textBox1.TextLength, 0);
});
}
_timeOutState = value;
}
}
TimeOutState _timeOutState = (TimeOutState)(-1); // Initialize to invalid state