Cómo capturo el evento de movimiento del mouse

Me gustaría capturar el evento de movimiento del mouse en mi forma principal. Aunque puedo conectar el MouseEventHandler para el formulario principal, el evento ya no se dispara cuando el cursor está sobre un UserControl o cualquier otro control. ¿Cómo me aseguro de que siempre tenga la posición del mouse?

Puede usar un gancho de mouse de bajo nivel. Vea este ejemplo y verifique el mensaje de WM_MOUSEMOVE en HookCallback.

También puede usar la clase IMessageFilter para captar los eventos del mouse y activar un evento para obtener la posición (nota: esto solo obtendrá la posición sobre la ventana, no fuera de ella):

 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 } } 

Aquí está la solución. Aunque puedo ver otra respuesta con un enfoque similar. Pero desde que lo escribí quiero publicarlo. Aquí MouseMessageFilter tiene un evento estático llamada MouseMove que puede suscribirse desde cualquier lugar dentro de la aplicación.

 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); } } } 

Probé la solución mencionada anteriormente proporcionada por @ SwDevMan81. Aunque funcionó bien, también tuve el problema @Randy Gamage mencionó “que la función MouseMoved se llama continuamente, aunque el mouse no se mueva. Deja de disparar cuando el mouse no está sobre la aplicación”. En cualquier caso, esto es lo que se me ocurrió:

En el constructor de formulario:

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

El controlador de eventos:

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

Y mi clase GlobalMouseHandler ligeramente modificada:

 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 } 

Espero que alguien pueda usarlo.