如何强制 DropDownList 样式的 ComboBox 仅在用户单击下拉按钮时打开?

发布于 2024-07-25 00:24:47 字数 194 浏览 4 评论 0原文

在 C# .NET 2.0 中,我有一个带有 ComboBoxStyle DropDownList 的 WinForms ComboBox。 但是,只要用户单击组合框上的任意位置,就会出现下拉菜单。 相反,我希望仅当用户明确单击下拉按钮时才打开它。 当用户单击组合框的其余部分时,我想为其分配键盘焦点,以便他或她可以在所选项目上使用一些键盘命令。 最好的方法是什么?

In C# .NET 2.0, I have a WinForms ComboBox with ComboBoxStyle DropDownList. However, the drop down appears whenever the user clicks anywhere on the combo box. Instead, I'd like to have it only open when the user explicitly clicks on the drop down button. When the user clicks on the rest of the combo box, I'd like to just assign it the keyboard focus so he or she can use some keyboard commands on the selected item. What's the best way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云仙小弟 2024-08-01 00:24:47

在其他答案的帮助下,我得出了这个快速解决方案:

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);
    }
}

After some help from the other answers, I arrived at this quick solution:

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);
    }
}
峩卟喜欢 2024-08-01 00:24:47

你有两个问题需要考虑。 第一个相当简单:确定是否应打开或关闭下拉菜单。 这段代码可以做到这一点:

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

第二个问题更重要——实际上阻止了下拉菜单的出现。 最简单的方法是:

comboBox1.DropDownStyle = ComboBoxStyle.DropDown;

但是,这允许在框中输入内容,而您可能不希望这样做。

我花了大约 15 分钟查看选项,看来为了防止出现下拉列表并同时防止用户在下拉列表中键入内容,您需要对控件进行子类化。 这样,您可以重写 OnMouseClick(),并且仅在单击按钮时调用 base.OnMouseClick() 。 它看起来像这样(未经测试):

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

You have two issues to consider. The first is rather simple: determine whether the dropdown should be opened or closed. This code can do that:

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

The second issue is more significant -- actually preventing the dropdown from appearing. The simplest approach is:

comboBox1.DropDownStyle = ComboBoxStyle.DropDown;

But, that allows typing into the box, which you may not want.

I spent about 15 minutes looking at options, and it appears that to prevent the dropdown from appearing and simultaneously prevent the user from typing into the dropdown, you would need to subclass the control. That way, you can override OnMouseClick(), and only call the base.OnMouseClick() when they did click on button. It would look something like this (untested):

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.
        }
    }
}
秋意浓 2024-08-01 00:24:47

您也许可以获得鼠标单击的 X、Y 位置,如果它不在下拉“图标”上(因为缺乏更好的词),您可以从那里强制它折叠。

You may be able to get the X,Y position of the mouse click, and from there you could force it collapsed if it isn't on the drop down "icon" (for lack of a better word).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文