如何捕获鼠标移动事件

我想在我的主窗体中捕获鼠标移动事件。 虽然我能够为主窗体连接MouseEventHandler ,但当光标位于UserControl或任何其他控件上时,事件不再触发。 如何确保始终保持鼠标位置。

您可以使用低级鼠标钩。 请参阅此示例并检查HookCallback中的WM_MOUSEMOVE消息。

您还可以使用IMessageFilter类来捕获鼠标事件并触发事件以获取位置(注意:这只会获取窗口上方的位置,而不是在窗口之外):

 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace GlobalMouseEvents { public partial class Form1 : Form { public Form1() { GlobalMouseHandler gmh = new GlobalMouseHandler(); gmh.TheMouseMoved += new MouseMovedEvent(gmh_TheMouseMoved); Application.AddMessageFilter(gmh); InitializeComponent(); } void gmh_TheMouseMoved() { Point cur_pos = System.Windows.Forms.Cursor.Position; System.Console.WriteLine(cur_pos); } } public delegate void MouseMovedEvent(); public class GlobalMouseHandler : IMessageFilter { private const int WM_MOUSEMOVE = 0x0200; public event MouseMovedEvent TheMouseMoved; #region IMessageFilter Members public bool PreFilterMessage(ref Message m) { if (m.Msg == WM_MOUSEMOVE) { if (TheMouseMoved != null) { TheMouseMoved(); } } // Always allow message to continue to the next filter control return false; } #endregion } } 

这是解决方案。 虽然我可以用类似的方法看到另一个答案。 但自从我写这篇文章以来我就想发布它。 这里MouseMessageFilter有一个静态事件调用MouseMove,您可以从应用程序中的任何位置订阅。

 static class Program { [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.AddMessageFilter(new MouseMessageFilter()); MouseMessageFilter.MouseMove += new MouseEventHandler(OnGlobalMouseMove); Application.Run(new MainForm()); } static void OnGlobalMouseMove(object sender, MouseEventArgs e) { Console.WriteLine(e.Location.ToString()); } } class MouseMessageFilter : IMessageFilter { public static event MouseEventHandler MouseMove = delegate { }; const int WM_MOUSEMOVE = 0x0200; public bool PreFilterMessage(ref Message m) { if (m.Msg == WM_MOUSEMOVE) { Point mousePosition = Control.MousePosition; MouseMove(null, new MouseEventArgs( MouseButtons.None, 0, mousePosition.X, mousePosition.Y,0)); } return false; } } 
 public partial class frmCaptureMouse : Form { [DllImport("user32.dll")] static extern IntPtr SetCapture(IntPtr hWnd); public frmCaptureMouse() { InitializeComponent(); } private void frmCaptureMouse_MouseMove(object sender, MouseEventArgs e) { try { lblCoords.Text = e.Location.X.ToString() + ", " + e.Location.Y.ToString(); } catch (Exception ex) { MessageBox.Show(ex.Message); } } private void btnCapture_Click(object sender, EventArgs e) { try { SetCapture(this.Handle); } catch (Exception ex) { MessageBox.Show(ex.Message); } } } 

我尝试了@ SwDevMan81提供的上述解决方案。 虽然它工作得很好,但我也有问题@Randy Gamage提到“即使鼠标没有移动也会连续调用MouseMoved函数。当鼠标不在应用程序上时它会停止触发”。 在任何情况下,这都是我提出的:

在表单构造函数中:

 GlobalMouseHandler.MouseMovedEvent += GlobalMouseHandler_MouseMovedEvent; Application.AddMessageFilter(new GlobalMouseHandler()); InitializeComponent(); 

事件处理程序:

 private void GlobalMouseHandler_MouseMovedEvent(object sender, MouseEventArgs e) { try { //Do whatever ... } catch { } } 

我稍微改变了GlobalMouseHandler类:

 public class GlobalMouseHandler : IMessageFilter { private const int WM_MOUSEMOVE = 0x0200; private System.Drawing.Point previousMousePosition = new System.Drawing.Point(); public static event EventHandler MouseMovedEvent = delegate { }; #region IMessageFilter Members public bool PreFilterMessage(ref System.Windows.Forms.Message m) { if (m.Msg == WM_MOUSEMOVE) { System.Drawing.Point currentMousePoint = Control.MousePosition; if (previousMousePosition != currentMousePoint) { previousMousePosition = currentMousePoint; MouseMovedEvent(this, new MouseEventArgs(MouseButtons.None, 0, currentMousePoint.X, currentMousePoint.Y, 0)); } } // Always allow message to continue to the next filter control return false; } #endregion } 

我希望有人可以使用它。