ventana - preguntar antes de cerrar formulario c#
¿Cómo configuro un evento click para un formulario? (6)
Tengo un formulario de ac # (llamémoslo MainForm) con una cantidad de controles personalizados. 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.
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
Este es un patrón común en el desarrollo, se llama el patrón Observer. Hay muchos ejemplos de patrones Observer y c # aquí es 1 ejemplo http://msdn.microsoft.com/en-us/library/ms954621.aspx pero tiene un buen google alrededor.
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.
La única manera que he logrado 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.
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 quién los "envió":
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.
Recomiendo crear un formulario base para que los otros formularios en su aplicación hereden. Agregue este código a su formulario 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 funcionará no solo para los controles de nivel superior, sino también para los controles anidados, como los controles ubicados dentro de los paneles.