2011-02-14 11 views
7

sin duda hay una manera conveniente de hacer esto:
Winforms: Interceptar el evento de ratón en el formulario principal en primer lugar, no en los controles

he implementado un "Mover la ventana" en el comportamiento de arrastre del ratón en mi forma principal,
y Me gustaría que el evento MouseClick/Move sea interceptado por el formulario, no por los controles que están en él.

Me gustaría encontrar un equivalente a/replicar la propiedad "TeclaDePresentaciónPreliminar" para eventos de ratón

Además quiero evitar Redirigir el evento de ratón para el método de formulario principal 12 veces en eventos de ratón 12 Controls individual (cuál es la solución fea que he encontrado hasta ahora)

¿Alguna idea?

+0

¿Los controles secundarios también manejan los eventos de clic/movimiento del mouse? – tzup

+0

Algunos de ellos, no todos. Y ciertamente quiero evitar redirigir el evento del mouse al método del formulario principal 12 veces en 12 controles –

+1

Puede usar un [filtro de mensajes] (http://stackoverflow.com/questions/4279732/). (Respuesta trivial convertida para comentar automáticamente.) – ulatekh

Respuesta

1

Sobre la base de sus comentarios,

implementar la funcionalidad de redirección del evento de ratón en una clase base, a continuación, hacer todos los controles que se derivan de la clase base.

Por lo tanto, solo implementa la funcionalidad una vez y luego todos sus controles "volverán a generar" el evento del mouse para ser capturado por el formulario principal.

Espero que esto ayude.

+0

Sí, pensé en eso ... Pero esto me hace cambiar el código heredado más de lo que estoy dispuesto a hacer. Solo me preguntaba si no había una forma de eludir por completo los controles ... –

4

Suscribirse a todos los controles de eventos MouseMove (consideran hacerlo de forma recursiva para los controles anidados)

foreach (Control control in Controls) 
    control.MouseMove += RedirectMouseMove; 

y elevar MouseMove dentro de este controlador de eventos

private void RedirectMouseMove(object sender, MouseEventArgs e) 
{ 
    Control control = (Control)sender; 
    Point screenPoint = control.PointToScreen(new Point(e.X, e.Y)); 
    Point formPoint = PointToClient(screenPoint); 
    MouseEventArgs args = new MouseEventArgs(e.Button, e.Clicks, 
     formPoint.X, formPoint.Y, e.Delta); 
    OnMouseMove(args); 
} 

Tenga en cuenta que los controles reciben MouseEvents con coordenadas locales de control. Entonces necesitas convertirlo a coordenadas de forma. Hay podría haber inconvenientes con controles anidados, pero lo dejo a usted (por ejemplo, llamar a Parent.PointToClient)

ACTUALIZACIÓN: Usted todavía será capaz de manejar los eventos del control - acaba de suscribirse a eventos una vez más .

+0

Como dije en otro comentario, me preguntaba si no había una forma de eludir por completo los controles ... –

+0

Pero KeyPreview funciona casi de la misma manera (se espera que se administre la propiedad de argumento de evento) - elude los controles y maneja el evento primero en el nivel del formulario. –

2

Se puede usar un gancho mundial ratón para interceptar eventos de ratón, hay una anulación sample on MSDN

1

el Método Control.PreProcessMessage:

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.preprocessmessage.aspx

Editar:

Parece PreProcessMessage podría no funcionar para eventos de mouse. Intente anular WndPrc en su lugar. Puede interceptar mensajes de ratón a ciencia cierta, pero hay que ver si los intercepta en el orden que desee:

http://bytes.com/topic/c-sharp/answers/752144-preprocessmessage

+0

¿Dónde hago eso? En la forma principal? Eso pasaría por alto los controles? –

+0

Si entendí tu pregunta correctamente, ¡sí! – Pedery

0

Se puede utilizar fácilmente para GlobalMouseKeyHook librarysistema de intercepción de ancho ratón posición.

Al hacer clic en el mouse, debe comprobar si la ubicación del mouse intersecta su formulario O si las ventanas debajo del mouse es su formulario.

Para hacer esto último lo que necesita la función API WindowFromPoint:

[DllImport("user32.dll", SetLastError = true)] 
    public static extern IntPtr WindowFromPoint([In] POINTAPI Point); 

    private void _mouseListener_MouseClick(object sender, MouseEventArgs e) 
    { 
     var localPoint = this.PointToClient(e.Location); 
     bool containsPoint = this.ClientRectangle.Contains(localPoint); 

     var windowHandle = WindowFromPoint(e.Location); 
     var ctl = (Form)Form.FromHandle(windowHandle); 
     bool mainFormClicked = ctl != null && ctl.Handle == this.Handle; 

     if(containsPoint && mainFormClicked ) 
     { 
       //form click is intercepted! 
     } 
    } 

En realidad yo uso esto cuando quiero interceptar clic fuera de mi forma (no hay otra manera). En tu caso, me vincularía a MouseClick de todos los controles por el bien del rendimiento (el gancho global es pesado).

Cuestiones relacionadas