我是新的C#,我正在使用
Windows窗体.我建立了一个应用程序,我希望在使用计时器停止鼠标(没有活动)5秒钟时显示按摩,当鼠标移动时计时器重置.
我有Form1与一些控件(按钮和TextBoxes)和一个Timer.我只是想做一些类似屏幕保护程序的事情,所以当Form1加载并且在一定时间内没有活动(鼠标停止)时,必须采取一个动作(例如show message).
我尝试了以下代码(作为示例),但它不能正常工作,当Form1加载定时器开始计数时,如果我移动鼠标(在i == 5之前),定时器重置并且它永远不会再次开始计数.
int i = 0;
private void Form1_Load(object sender, EventArgs e)
{
timer1.Start();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
i = 0;
timer1.Stop();
textBox1.Text = i.ToString();
}
private void Form1_MouseHover(object sender, EventArgs e)
{
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
i = i + 1;
textBox1.Text = i.ToString();
if(i==5)
{
MessageBox.Show("Time is over");
}
}
我不知道我是否使用了正确的鼠标事件,我甚至不知道在这种情况下使用这些事件是否正确.如果鼠标移动5秒钟,如何显示消息?
最佳答案 不幸的是,WinForms没有像WPF这样的PreviewMouseMove事件,因此当您将鼠标移到Control上时,Form将永远不会知道它.但是,每次在表单中注册鼠标事件时,都可以使用系统函数
SetWindowsHookEx并重置计时器.
如果您对上次用户在操作系统上的任何位置(如屏幕保护程序)进行任何类型的输入感兴趣,您也应该查看GetLastInputInfo功能.
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public enum HookType : int
{
WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_HARDWARE = 8,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
}
[StructLayout(LayoutKind.Sequential)]
public struct MouseHookStruct
{
public POINT pt;
public int hwnd;
public int hitTestCode;
public int dwExtraInfo;
}
[DllImport("user32.dll", SetLastError = true)]
static extern int SetWindowsHookEx(HookType hook, HookProc callback, IntPtr hInstance, uint dwThreadId);
[DllImport("user32.dll", SetLastError = true)]
static extern int CallNextHookEx(int hook, int code, IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll")]
static extern int GetCurrentThreadId();
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
private static int _hHook;
private readonly Timer _timer1;
public Form1()
{
InitializeComponent();
_timer1 = new Timer();
// setting the interval to 5000 is a lot easier than counting up to 5 ;)
_timer1.Interval = 5000;
_timer1.Tick += Timer1OnTick;
}
private void Form1_Load(object sender, EventArgs e)
{
// hook up to mouse events (or keyboard with WH_KEYBOARD)
_hHook = SetWindowsHookEx(HookType.WH_MOUSE, MouseHookProc, IntPtr.Zero, (uint)GetCurrentThreadId());
_timer1.Start();
}
// This function will get called every time there is a mouse event
private int MouseHookProc(int code, IntPtr wParam, IntPtr lParam)
{
// Mouse event --> reset Timer
_timer1.Stop();
_timer1.Start();
return CallNextHookEx(_hHook, code, wParam, lParam);
}
// 5000 ms without any mouse events --> show message
private void Timer1OnTick(object sender, EventArgs eventArgs)
{
//Stop timer, Show message, start timer
_timer1.Stop();
MessageBox.Show("You have been idle for " + _timer1.Interval + " ms!");
_timer1.Start();
}
}
}