2008-10-07 12 views
5

Tengo un formulario C# (llamémoslo MainForm) con una serie de controles personalizados sobre él. Me gustaría que el método MainForm.OnClick() se active cada vez que alguien haga clic en el formulario independientemente de si el clic sucedió en el formulario o si el clic fue en uno de los controles personalizados. Estoy buscando un comportamiento similar a la característica KeyPreview de los formularios, excepto por los clics del mouse en lugar de presionar las teclas.¿Cómo configuro un evento de clic para un formulario?

Respuesta

2

En el evento ControlAdded del formulario, agregue un controlador MouseClick al control, con la dirección del evento click del formulario. No lo he probado, pero podría funcionar.

Private Sub Example_ControlAdded(ByVal sender As Object, ByVal e As System.Windows.Forms.ControlEventArgs) Handles Me.ControlAdded 

    AddHandler e.Control.MouseClick, AddressOf Example_MouseClick 
End Sub 

Private Sub Example_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick 
    MessageBox.Show("Click") 
End Sub 
+0

Esto todavía parece ser un truco, pero esta parece ser la mejor opción que tengo. – Mykroft

0

Hacer clic en un espacio abierto en el formulario es fácil, pero para obtener un clic que esté realmente en un control, necesitará la cooperación de ese control para enviarlo al formulario.

Una posibilidad es colocar un control transparente sobre todo el formulario, y aceptar clics sobre eso, tratar con ellos, y luego pasarlos al control adecuado debajo.

+0

Creo que debe haber una solución más elegante que esta. – Mykroft

1

La única forma en que he podido hacer esto es manejar el evento [c] Click [/ c] de cada control. No creo que el evento se haya planteado antes de que el control lo procese.

En WPF, hay eventos de vista previa "tunelización" que proporcionan esta funcionalidad, pero eso realmente no lo ayuda en WinForms.

+0

Bueno, es demasiado tarde para cambiar a WPF ahora, pero tendré que considerar seriamente su uso en el futuro, supongo. – Mykroft

1

Puede enganchar todos los eventos del control, si lo desea, y luego monitorear de esa manera. Supongo que hay una gran manera de apostar Win32 para atraparlos a todos, pero eso está más allá de mí en este momento.

public Form1() 
    { 
     InitializeComponent(); 
     HookEvents(); 
    } 

    private void HookEvents() { 
     foreach (Control ctl in this.Controls) { 
      ctl.MouseClick += new MouseEventHandler(Form1_MouseClick); 
     } 
    } 

    void Form1_MouseClick(object sender, MouseEventArgs e) 
    { 
     LogEvent(sender, "MouseClick"); 
    } 

    // and then this just logs to a multiline textbox you have somwhere on the form 
    private void LogEvent(object sender, string msg) { 
     this.textBox1.Text = string.Format("{0} {1} ({2}) \n {3}", 
      DateTime.Now.TimeOfDay.ToString(), 
      msg, 
      sender.GetType().Name, 
      textBox1.Text 
      ); 
    } 

La salida es algo como esto, que muestra todos los eventos y que "enviado" a ellos:

14:51:42.3381985 MouseClick (Form1) 
14:51:40.6194485 MouseClick (RichTextBox) 
14:51:40.0100735 MouseClick (TextBox) 
14:51:39.6194485 MouseClick (Form1) 
14:51:39.2131985 MouseClick (RichTextBox) 
14:51:38.8694485 MouseClick (Button) 

HTH.

6

Recomiendo crear un formulario base para que hereden los otros formularios en su aplicación. Añadir este código a su forma base para crear un nuevo evento llamado GlobalMouseClickEventHandler:

namespace Temp 
{ 
    public delegate void GlobalMouseClickEventHander(object sender, MouseEventArgs e); 

    public partial class TestForm : Form 
    { 
     [Category("Action")] 
     [Description("Fires when any control on the form is clicked.")] 
     public event GlobalMouseClickEventHander GlobalMouseClick; 

     public TestForm() 
     { 
      InitializeComponent(); 
      BindControlMouseClicks(this); 
     } 

     private void BindControlMouseClicks(Control con) 
     { 
      con.MouseClick += delegate(object sender, MouseEventArgs e) 
      { 
       TriggerMouseClicked(sender, e); 
      }; 
      // bind to controls already added 
      foreach (Control i in con.Controls) 
      { 
       BindControlMouseClicks(i); 
      } 
      // bind to controls added in the future 
      con.ControlAdded += delegate(object sender, ControlEventArgs e) 
      { 
       BindControlMouseClicks(e.Control); 
      };    
     } 

     private void TriggerMouseClicked(object sender, MouseEventArgs e) 
     { 
      if (GlobalMouseClick != null) 
      { 
       GlobalMouseClick(sender, e); 
      } 
     } 
    } 
} 

Esta solución va a trabajar no sólo para los controles de primer nivel, sino también anidado controles tales como controles colocados en el interior de los paneles.

+0

¡Muchas gracias! Una solución simple y elegante. Me pregunto por qué no hay algo equivalente a 'KeyPreview' para los clics del mouse –

Cuestiones relacionadas