c# – 我用什么事件进行鼠标移动和鼠标停止

我是新的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();
        }
    }
}
点赞