Capturar eventos de mouse de cada componente en C # WInForm

Tengo un problema con MouseEvents en mi aplicación WinForm C #. Quiero obtener TODOS los clics del mouse en mi aplicación, pero no quiero poner un oyente en cada componente secundario ni usar el gancho del mouse de Windows.

En Flash podría poner un oyente en el escenario para obtener todos los eventos de ratón en la película. ¿Hay tal cosa en C #? ¿Un mouseListener global?


Editar: creo esta clase desde IMessageFilter y use Application.AddMessageFilter.

public class GlobalMouseHandler : IMessageFilter{ private const int WM_LBUTTONDOWN = 0x201; public bool PreFilterMessage(ref Message m){ if (m.Msg == WM_LBUTTONDOWN) { // Do stuffs } return false; } } 

Y coloque este código en los controles que necesitan escuchar clics globales:

 GlobalMouseHandler globalClick = new GlobalMouseHandler(); Application.AddMessageFilter(globalClick); 

¡Gracias por la ayuda!

Una manera directa de hacerlo es agregar un filtro de bucle de mensaje llamando a Application.AddMessageFilter y escribiendo una clase que implemente la interfaz IMessageFilter .

A través de IMessageFilter.PreFilterMessage , su clase puede ver cualquier mensaje de entrada que pase por el bucle de mensajes de su aplicación. PreFilterMessage también puede decidir si pasa estos mensajes al control específico al que están destinados.

Una de las complejidades que presenta este enfoque es tener que lidiar con los mensajes de Windows, a través de la estructura del mensaje pasada a su método PreFilterMessage . Esto significa hacer referencia a la documentación de Win32 en WM\_LBUTTONDOWN, WM\_MOUSEMOVE , WM\_LBUTTONUP , etc., en lugar de los eventos convencionales MouseDown , MouseMove y MouseUp .

Clase de muestra

 class CaptureEvents : IMessageFilter { #region IMessageFilter Members public delegate void Callback(int message); public event Callback MessageReceived; IntPtr ownerWindow; Hashtable interestedMessages = null; CaptureEvents(IntPtr handle, int[] messages) { ownerWindow = handle; for(int c = 0; c < messages.Length ; c++) { interestedMessages[messages[c]] = 0; } } public bool PreFilterMessage(ref Message m) { if (m.HWnd == ownerWindow && interestedMessages.ContainsKey(m.Msg)) { MessageReceived(m.Msg); } return true; } #endregion } 

Si no desea manejar los mensajes anulando Form.PreProcessMessage o Form.WndProc, puede crear una subclase de Formulario para conectar un controlador de eventos a todos los eventos MouseClick de los diversos controles en el formulario.
EDITAR: se olvidó de volver a recurrir a través de controles secundarios de controles en el formulario.

  public class MousePreviewForm : Form { protected override void OnClosed(EventArgs e) { UnhookControl(this as Control); base.OnClosed(e); } protected override void OnLoad(EventArgs e) { base.OnLoad(e); HookControl(this as Control); } private void HookControl(Control controlToHook) { controlToHook.MouseClick += AllControlsMouseClick; foreach (Control ctl in controlToHook.Controls) { HookControl(ctl); } } private void UnhookControl(Control controlToUnhook) { controlToUnhook.MouseClick -= AllControlsMouseClick; foreach (Control ctl in controlToUnhook.Controls) { UnhookControl(ctl); } } void AllControlsMouseClick(object sender, MouseEventArgs e) { //do clever stuff here... throw new NotImplementedException(); } } 

Sus formularios deberían derivarse de MousePreviewForm no System.Windows.Forms.Form.

Eche un vistazo a este artículo . Acurruca de manera recursiva todos los eventos de control y los transmite. También puede anular WndProc en su formulario.