【问题标题】:What events do I use for mouse move and mouse stop我为鼠标移动和鼠标停止使用什么事件
【发布时间】:2016-06-03 16:46:53
【问题描述】:

我是新的 C#,我正在使用 Windows 窗体。我构建了一个应用程序,如果鼠标使用计时器停止(没有活动正在进行)5 秒,并且当鼠标移动时计时器被重置,我想在其中显示按摩。

我有 Form1 和一些控件(ButtonsTextBoxes)和 Timer。我只是想做一个屏幕保护程序之类的事情,所以当Form1 加载并且在一定时间内没有活动(鼠标停止)时,必须采取行动(例如显示消息)。

我尝试了以下代码(作为示例),但效果不佳,当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 秒没有移动,如何显示消息?

【问题讨论】:

  • 而不是 MouseHover 事件将 timer1.Start(); 直接放在 MouseMove 事件的末尾...
  • 您必须查看鼠标的位置。你怎么知道它是否移动了?如果位置相同,则说明它没有移动。
  • btw HanletEscano 在效率方面提出了更好的解决方案...
  • 您忘记再次调用 timer1.Start()。这不是正确的做法,您需要实现 IMessageFilter 以便您可以看到 every 移动。 Like this.

标签: c#


【解决方案1】:

不幸的是,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();
        }
    }
}

【讨论】:

    猜你喜欢
    • 2014-06-30
    • 2010-09-18
    • 2015-07-06
    • 1970-01-01
    • 1970-01-01
    • 2021-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多