'How to auto open a ComboBox when focused?
I have a Form which contains several ComboBoxes.
I want one ComboBox of them to open the elements list when it gets the focus, both from keyboard and mouse.
The DroppedDown
property of the ComboBox class manages the visibility of the elements list.
The event that most fits my needs is Enter
, so the code I wrote is:
private void comboBox1_Enter(object sender, EventArgs e)
{
this.comboBox1.DroppedDown = true;
}
It works, but when directly clicking on the icon located on the right part of the ComboBox which does NOT have the focus, the elements list opens up and the suddenly disappears after its opening.
I've tried many ways to fix this weird behavior, checking the Focused
property or using other events like DropDown
or MouseClick
, without getting any acceptable result.
Solution 1:[1]
A simple way (which doesn't force you to override a ComboBox
derived Control's WndProc
) is to simulate a HitTest, testing whether the MouseDown occurred on the ComboBox
button area; then, set DroppedDown = true;
only if it didn't.
Thus, when the Mouse is clicked on the Button, you won't cause a double effect, moving the Focus in an unexpected way (for the Control).
GetComboBoxInfo() is used to retrieve the correct bounds of the ComboBox Button, whatever the current layout is (LTR or RTL).
private void comboBox1_Enter(object sender, EventArgs e)
{
var combo = sender as ComboBox;
if (!combo.DroppedDown) {
var buttonRect = GetComboBoxButtonInternal(combo.Handle);
if (!buttonRect.Contains(combo.PointToClient(Cursor.Position))) {
combo.DroppedDown = true;
Cursor = Cursors.Default;
}
}
}
Declarations for the GetComboBoxInfo()
function:
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
internal static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);
[StructLayout(LayoutKind.Sequential)]
internal struct COMBOBOXINFO {
public int cbSize;
public Rectangle rcItem;
public Rectangle rcButton;
public int buttonState;
public IntPtr hwndCombo;
public IntPtr hwndEdit;
public IntPtr hwndList;
}
internal static Rectangle GetComboBoxButtonInternal(IntPtr cboHandle) {
var cbInfo = new COMBOBOXINFO();
cbInfo.cbSize = Marshal.SizeOf<COMBOBOXINFO>();
GetComboBoxInfo(cboHandle, ref cbInfo);
return cbInfo.rcButton;
}
Solution 2:[2]
Create a new class the is inherited from ComboBox:
public class Combo : ComboBox
{
protected override void OnClick(EventArgs e)
{
if (!DroppedDown) base.OnClick(e);
}
}
And in its click call base.OnClick(e);
if its not dropped down.
use this one instead of combobox. (Basically click event will be ignored if dropped down)
Solution 3:[3]
Use the following code on your form constructor:
this.comboBox1.GotFocus += (sender,args) => comboBox1.DroppedDown = true;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | Ashkan Mobayen Khiabani |
Solution 3 | joppiesaus |