2009-06-25 9 views
5

In C# .NET 2.0, ho un ComboBox WinForms con DropDownList di ComboBoxStyle. Tuttavia, il menu a discesa viene visualizzato ogni volta che l'utente fa clic in qualsiasi punto della casella combinata. Invece, mi piacerebbe averlo aperto solo quando l'utente fa clic esplicitamente sul pulsante a discesa. Quando l'utente fa clic sul resto della casella combinata, desidero semplicemente assegnargli il focus della tastiera in modo che lui o lei possano utilizzare alcuni comandi da tastiera sull'elemento selezionato. Qual'è il miglior modo per farlo?Come posso forzare l'apertura di un ComboBox di DropDownList solo quando l'utente fa clic sul pulsante a discesa?

risposta

4

Dopo qualche aiuto da parte delle altre risposte, sono arrivato a questa soluzione rapida:

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

Si può essere in grado di ottenere la posizione X, Y del clic del mouse e da lì si può forzare il collasso se non è presente nella "icona" a discesa (per mancanza di una parola migliore).

1

Hai due problemi da considerare. Il primo è piuttosto semplice: determina se il menu a discesa deve essere aperto o chiuso. Questo codice può farlo:

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. 
     } 
    } 

La seconda questione è più significativo - in realtà impedendo la discesa di apparire. L'approccio più semplice è:

comboBox1.DropDownStyle = ComboBoxStyle.DropDown; 

Tuttavia, ciò consente di digitare nella casella, che potrebbe non essere desiderato.

Ho trascorso circa 15 minuti a esaminare le opzioni e sembra che per evitare che il menu a discesa venga visualizzato e impedire allo stesso tempo all'utente di digitare nel menu a discesa, è necessario creare una sottoclasse del controllo. In questo modo, puoi ignorare OnMouseClick() e chiamare solo base.OnMouseClick() quando hanno fatto clic sul pulsante. Sarebbe simile a questa (non testata):

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

La larghezza della barra di scorrimento è stato utile, ma utilizzando gli eventi WinForms del mouse/funzioni non è utile. Sono chiamati troppo tardi. – Eric

+0

Gli eventi e le funzioni di WinForm vengono richiamati alla stessa ora dei normali messaggi di Windows. È la gestione di loro che conta. Trovare un modo per prevenire il comportamento predefinito è la sfida, dal momento che i tempi sono gli stessi. –

+0

Stavo scrivendo metaforicamente. Internamente, sembra che prima che gli eventi del mouse di WinForms vengano mai chiamati, viene visualizzato il menu a discesa E viene inviato l'evento a discesa. Pertanto, l'utilizzo degli eventi WinForms non è sufficiente per impedire la visualizzazione dell'elenco a discesa. – Eric

Problemi correlati