Estoy creando un cuadro desplegable personalizado, y quiero registrarme cuando se presiona el mouse fuera del cuadro desplegable, para ocultarlo. ¿Es posible detectar un clic fuera de un control? ¿o debería hacer algún mecanismo en el formulario que contiene y verificar si hay algún menú desplegable abierto?¿Hay alguna forma de detectar un clic de ratón fuera de un control de usuario?
Respuesta
Así que finalmente entiendo que solo quiere que se cierre cuando el usuario haga clic fuera de él. En ese caso, el Leave
event debería funcionar bien ... Por alguna razón, tuve la impresión de que quería que se cerrara cada vez que movían el mouse fuera de su menú desplegable personalizado. El evento Leave
se genera cada vez que el control pierde el foco, y si el usuario hace clic en otra cosa, sin duda perderá el foco, ya que lo que hicieron clic en el foco gana.
La documentación también se dice que este evento cascadas arriba y abajo de la cadena de control según sea necesario:
Los
Enter
yLeave
eventos son jerárquicos y caerá en cascada hacia arriba y abajo por la cadena principal hasta que se alcanza el control adecuado. Por ejemplo, supongamos que tiene un Formulario con dos controles GroupBox y cada control GroupBox tiene un control TextBox. Cuando el cursor se mueve de un cuadro de texto a otro, se genera el eventoLeave
para el cuadro de texto y el cuadro de grupo, y se genera el eventoEnter
para el otro cuadro de cuadro y cuadro de texto.
Reemplazar el método de su UserControl OnLeave
es la mejor manera de manejar esto:
protected override void OnLeave(EventArgs e)
{
// Call the base class
base.OnLeave(e);
// When this control loses the focus, close it
this.Hide();
}
Y a continuación, para propósitos de prueba, he creado un formulario que muestra el control de usuario desplegable de comando:
public partial class Form1 : Form
{
private UserControl1 customDropDown;
public Form1()
{
InitializeComponent();
// Create the user control
customDropDown = new UserControl1();
// Add it to the form's Controls collection
Controls.Add(customDropDown);
customDropDown.Hide();
}
private void button1_Click(object sender, EventArgs e)
{
// Display the user control
customDropDown.Show();
customDropDown.BringToFront(); // display in front of other controls
customDropDown.Select(); // make sure it gets the focus
}
}
Todo funciona perfectamente con el código anterior, excepto por una cosa: si el usuario hace clic en un área en blanco del formulario, el UserCont rol no se cierra. Hmm, ¿por qué no? Bueno, porque la forma en sí misma no quiere el foco. Solo los controles pueden enfocarse, y no hicimos clic en un control. Y como nada más le robó el foco, el evento Leave
nunca se levantó, lo que significa que el UserControl no sabía que se suponía que debía cerrarse.
Si necesita que el UserControl se cierre cuando el usuario hace clic en un área en blanco en el formulario, necesita algún manejo especial de casos para eso. Ya que dices que eres sólo se preocupa por clics, usted puede controlar el evento Click
para el formulario, y establecer el foco a un control diferente:
protected override void OnClick(EventArgs e)
{
// Call the base class
base.OnClick(e);
// See if our custom drop-down is visible
if (customDropDown.Visible)
{
// Set the focus to a different control on the form,
// which will force the drop-down to close
this.SelectNextControl(customDropDown, true, true, true, true);
}
}
Sí, esta última parte se siente como un hack . La mejor solución, como han mencionado otros, es usar el SetCapture
function para indicar a Windows que capture el mouse sobre la ventana de UserControl. El control Capture
property proporciona una forma aún más simple de hacer lo mismo.
Usted probablemente está buscando para el evento licencia:
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.leave.aspx
Dejar produce cuando el foco de entrada deja el control.
Pero los menús desplegables "normales" permanecen abiertos y no se cierran hasta que se hace clic en el mouse. ¿Tienes alguna idea de cómo hacer esto? – Bildsoe
Técnicamente, necesitará p/invocar SetCapture() para recibir eventos de clic que suceden fuera de su control.
Pero en su caso, manejar el evento Leave, como sugiere @Martin, debería ser suficiente.
EDIT: bien en busca de un ejemplo de uso de SetCapture()
, me encontré con la propiedad Control.Capture, de los cuales yo no era consciente. Usar esa propiedad significa que no tendrás que p/invocar nada, lo cual siempre es bueno en mi libro.
Por lo tanto, tendrá que establecer Capture
a true
cuando se muestra el menú desplegable, a continuación, determinar si el puntero del ratón se encuentra el control en el controlador de eventos clic y, si no lo hace, configurar Capture
a false
y cerrar la desplegable.
Tengo otros controles en el control de usuario, y cuando estos están enfocados, el evento Leave se activa para usercontrol. – Bildsoe
@Bildsoe, si entiendo correctamente, desea dejar el menú desplegable abierto cuando el usuario hace clic en otro control dentro de su control de usuario, pero ciérrelo si hace clic fuera de su control de usuario. –
@ Frédéric Hamidi: el menú desplegable también debe cerrarse cuando el usuario hace clic en un control dentro de mi control de usuario, pero no cuando el usuario coloca otro control dentro. – Bildsoe
He hecho esto yo mismo, y así es como lo hice.
Cuando se abre la gota abajo, registrar un evento click en forma parental del control:
this.Form.Click += new EventHandler(CloseDropDown);
Pero esto sólo te lleva la mitad del camino. Es probable que también desee que su menú desplegable se cierre cuando la ventana actual se desactiva. La forma más fiable de detectar esto tiene para mí estado a través de un temporizador que comprueba la que se encuentra la ventana activa:
[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
y
var timer = new Timer();
timer.Interval = 100;
timer.Tick += (sender, args) =>
{
IntPtr f = GetForegroundWindow();
if (this.Form == null || f != this.Form.Handle)
{
CloseDropDown();
}
};
Usted debe, por supuesto, sólo dejar correr el cronómetro cuando el descenso es visible. Además, es probable que haya algunos otros eventos en los padres forman te gustaría registrar cuando el descenso se abre:
this.Form.LocationChanged += new EventHandler(CloseDropDown);
this.Form.SizeChanged += new EventHandler(CloseDropDown);
Eso sí, no se olvide de cancelar el registro de todos estos eventos en el método CloseDropDown :)
EDIT:
me olvidaba, también debe registrar el evento Dejar de controlar para ver si otro control se activa/hace clic en:
this.Leave += new EventHandler(CloseDropDown);
creo Me'v Ahora lo tengo, esto debería cubrir todas las bases. Avísame si me estoy perdiendo algo.
Hmm, no. No haga sondeos periódicamente para la ventana de primer plano actual. Eso es definitivamente un mal uso de la API. Tienes una manera perfectamente buena de hacer exactamente lo que se te pide aquí. Implica capturar el mouse. Busca 'SetCapture'. –
Excelente sugerencia @Cody, me aseguraré de revisarlo en caso de que necesite actualizar este control. Te recomiendo que eches un vistazo a ti mismo @Bildsoe. También me gustaría señalar que generalmente implemento mi menú desplegable como un formulario separado, por lo que tendrías que tenerlo en cuenta usando el enfoque GetForegroundWindow. –
la manija del formulario evento MouseDown
, o anular OnMouseDown
método del formulario:
enter code here
Y luego:
protected override void OnMouseDown(MouseEventArgs e)
{
if (!theListBox.Bounds.Contains(e.Location))
{
theListBox.Visible = false;
}
}
La Contiene viejo método System.Drawing.Rectangle
se puede utilizar para indicar si un punto es contenido dentro de un rectángulo. La propiedad Bounds de un control es , el Rectangle
externo definido por los bordes del control.La ubicación propiedad del MouseEventArgs
es el punto relativo al control que recibió el evento MouseDown
. La propiedad Bounds de un Control en un Formulario es relativa al Formulario.
- 1. ¿Hay alguna forma de detectar si un objeto está bloqueado?
- 2. ¿Hay alguna forma de detectar un lenguaje RTL en Java?
- 3. ¿Hay alguna forma de detectar un software de registro clave?
- 4. ¿Detectar un clic fuera del elemento?
- 5. ¿Hay alguna forma de tener hangouts fuera de google +?
- 6. ¿Hay alguna forma de detectar si un usuario tiene conexión wifi con php o javascript?
- 7. ¿Cómo puede un control controlar un clic del mouse fuera de ese control?
- 8. jQuery -. Detectar cuando un usuario hace clic fuera de un tipo de entrada de campo de texto
- 9. La detección de un solo clic del ratón en MFC
- 10. ¿Hay alguna forma de agregar un evento onclick a un control de servidor de etiquetas ASP.NET?
- 11. ¿Hay alguna forma de multirreproducir un SqlDataReader?
- 12. ¿Hay alguna forma de instanciar un NSManagedObject sin insertarlo?
- 13. ¿Hay alguna forma de detectar SMS en E-Mail Gateways?
- 14. ¿Hay alguna forma de detectar matrices circulares en PHP puro?
- 15. ¿Hay alguna forma de colocar controles internos dentro de un control personalizado de ASP.NET?
- 16. ¿Hay alguna manera de detectar bloqueadores de flash?
- 17. ¿Hay alguna manera de almacenar de forma segura los datos de usuario en un dispositivo Android?
- 18. Cómo llegar latitud/longitud de un clic del ratón con Bing Mapas AJAX Control v7
- 19. ¿Hay alguna forma de controlar los cambios en un objeto?
- 20. ¿Hay alguna forma de seleccionar un ancla segue programáticamente?
- 21. ¿Hay alguna forma de agregar un número par de dígitos?
- 22. ¿Hay alguna forma de comentar un gran fragmento de código?
- 23. ¿Hay alguna forma de obtener la dirección de un registro?
- 24. ¿Hay alguna forma de filtrar un rastreo de SQL Profiler?
- 25. ¿Hay alguna forma de pasar el iPhone?
- 26. ¿Hay alguna forma de detectar MySQL y errores de base de datos en PHP?
- 27. OpenCV vía python: ¿Hay una forma rápida de cero píxeles fuera de un conjunto de rectángulos?
- 28. ¿Hay alguna forma de detectar si un archivo javascript externo está completamente cargado?
- 29. ¿Hay alguna forma de anclar un ancla en css?
- 30. Ocultar en el teclado iOS cuando el usuario hace clic fuera de un cuadro de texto
¿No podría usar el evento "Leave" de un control? Esto se disparará cuando tu nuevo control pierda enfoque, creo. –
¿Detectando cuándo el menú desplegable pierde el foco, tal vez? ¿Qué sucede si te alejas del control, probablemente también quieras cerrar/ocultar el menú desplegable en ese punto? –