Tengo un problema con MouseEvents en mi WinForm aplicación de C#.

Quiero llegar todos clics del ratón en mi aplicación, pero no quiero poner un detector en cada componente hijo ni el uso de ratón de Windows gancho.

En Flash podría colocar un detector en el Escenario para obtener todos los MouseEvents en la película.

Hay tal cosa en C#? Un mundial MouseListener?


Edición:

Puedo crear esta clase de IMessageFilter ans utilizadas de la Aplicación.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 poner este código en los Controles que necesitan escuchar global clics:

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

4 Comentarios

  1. 15

    Una manera sencilla de hacer esto es agregar un mensaje de filtro de lazo llamando Application.AddMessageFilter y escribir una clase que implementa la IMessageFilter interfaz.

    A través de IMessageFilter.PreFilterMessage, su clase se para ver cualquiera de las entradas de los mensajes que pasan a través de la aplicación del bucle de mensajes. PreFilterMessage también puede decidir si pasar estos mensajes en el control específico para el cual están destinados.

    Una pieza de la complejidad que este enfoque presenta es tener que lidiar con los mensajes de Windows, a través del Mensaje struct pasa a su PreFilterMessage método. Esto significa refiriéndose a la Win32 documentación en WM\_LBUTTONDOWN, WM\_MOUSEMOVE, WM\_LBUTTONUP etc, en lugar de la convencional MouseDown, MouseMove y MouseUp eventos.

    • Gracias por la ayuda! Todo funciona correctamente. He utilizado la Aplicación.AddMessageFilter con suscess. Puedo conectar los eventos de ratón y crear una C# MouseEventHandler para enviar el evento en WinForm nivel de otros controles.
  2. 5

    Clase De Ejemplo

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

    Echa un vistazo a este artículo. En forma recursiva hoooks todos los eventos de control y las emisiones de ellos. Usted también podría invalidar WndProc en su forma.

    • He intentado reemplazar WinProc, pero terminó con el mismo problema: clics de ratón fueron solo se captura cuando hice clic directamente sobre el formulario. Si tengo un niño de Control Winproc no fue llamado.
  4. 3

    Si no desea manejar los mensajes reemplazando Forma.PreProcessMessage o Formulario.WndProc, entonces usted podría subclase Forma de enganchar a un controlador de eventos para todos los eventos Click de los distintos controles en el formulario.

    EDIT: olvidé de buscar recursivamente a través de los controles secundarios de los 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 formas, se tendrían que derivan de MousePreviewForm no del Sistema.Windows.Los formularios.Forma.

    • Usted puede incluso utilizar el Formulario.OnControlAdded evento para aplicar la AllControlsMouseClick controlador.
    • Pero no puedo solo bucle a través de la primera Infancia de la forma, necesito ir a la profundidad en cada Control y agregar el AllControlsMouseClick a su Niño también.
    • La recursividad de childs componets es una buena tatic. Pero no quiero añadir un detector para cada control. Para los eventos de ratón de la Aplicación.AddMessageFilter trabajo, pero creo que su idea es buena para otros tipos de eventos. Gracias por la ayuda!

Dejar respuesta

Please enter your comment!
Please enter your name here