2009-06-25 23 views
5

En C# .NET 2.0, tengo un ComboBox de WinForms con ComboBoxStyle DropDownList. Sin embargo, el menú desplegable aparece cada vez que el usuario hace clic en cualquier lugar del cuadro combinado. En cambio, me gustaría que solo se abra cuando el usuario hace clic explícitamente en el botón desplegable. Cuando el usuario hace clic en el resto del cuadro combinado, me gustaría asignarle el foco del teclado para que pueda usar algunos comandos del teclado en el elemento seleccionado. ¿Cuál es la mejor manera de hacer esto?¿Cómo puedo forzar que un ComboBox estilo DropDownList solo se abra cuando el usuario hace clic en el botón desplegable?

Respuesta

4

Después de un poco de ayuda de las otras respuestas, llegué a esta solución rápida:

public class MyComboBox : ComboBox 
{ 
    public MyComboBox() 
    { 
     FlatStyle = FlatStyle.Popup; 
     DropDownStyle = ComboBoxStyle.DropDownList; 
    } 

    protected override void WndProc(ref Message m) 
    { 
     if (m.Msg == 0x0201 /* WM_LBUTTONDOWN */ || m.Msg == 0x0203 /* WM_LBUTTONDBLCLK */) 
     { 
      int x = m.LParam.ToInt32() & 0xFFFF; 
      if (x >= Width - SystemInformation.VerticalScrollBarWidth) 
       base.WndProc(ref m); 
      else 
      { 
       Focus(); 
       Invalidate(); 
      } 
     } 
     else 
      base.WndProc(ref m); 
    } 
} 
0

Puede obtener la posición X, Y del clic del mouse, y desde allí puede forzarlo a colapsar si no está en el "icono" desplegable (a falta de una palabra mejor).

1

Tiene dos problemas a tener en cuenta. El primero es bastante simple: determinar si el menú desplegable debe abrirse o cerrarse. Este código puede hacer eso:

void comboBox1_MouseClick(object sender, MouseEventArgs e) 
    { 
     ComboBox combo = sender as ComboBox; 
     int left = combo.Width - (SystemInformation.HorizontalScrollBarThumbWidth + SystemInformation.HorizontalResizeBorderThickness); 
     if (e.X >= left) 
     { 
      // They did click the button, so let it happen. 
     } 
     else 
     { 
      // They didn't click the button, so prevent the dropdown. 
     } 
    } 

El segundo problema es más significativo: en realidad impide que aparezca el menú desplegable. El enfoque más simple es:

comboBox1.DropDownStyle = ComboBoxStyle.DropDown; 

Pero, que permite escribir en la caja, que puede que no desee.

Pasé unos 15 minutos mirando las opciones, y parece que para evitar que aparezca el menú desplegable y al mismo tiempo evitar que el usuario escriba en el menú desplegable, necesitaría subclasificar el control. De esta forma, puede anular OnMouseClick() y solo llamar a base.OnMouseClick() cuando hicieron clic en el botón. Se vería algo como esto (no probado):

public class CustomComboBox : ComboBox 
{ 
    protected override void OnMouseClick(MouseEventArgs e) 
    { 
     base.OnMouseClick(e); 

     int left = this.Width - (SystemInformation.HorizontalScrollBarThumbWidth + SystemInformation.HorizontalResizeBorderThickness); 
     if (e.X >= left) 
     { 
      // They did click the button, so let it happen. 
      base.OnMouseClick(e); 
     } 
     else 
     { 
      // They didn't click the button, so prevent the dropdown. 
      // Just do nothing. 
     } 
    } 
} 
+0

El ancho de barra de desplazamiento era útil, pero utilizando los eventos WinForms ratón/funciones no es útil. Se llaman demasiado tarde. – Eric

+0

Los eventos y funciones de WinForms se invocan al mismo tiempo que los mensajes normales de Windows. Es el manejo de ellos lo que importa. Encontrar una forma de evitar el comportamiento predeterminado es el desafío, ya que el tiempo es el mismo. –

+0

Estaba escribiendo metafóricamente. Internamente, parece que antes de que se llame a los eventos de mouse de WinForms, aparece el menú desplegable Y se envía el evento desplegable. Por lo tanto, usar los eventos de WinForms no es suficiente para evitar que aparezca el menú desplegable. – Eric

Cuestiones relacionadas