如何从组合框中永久删除文本选择突出显示?

时间:2021-03-13 10:48:47

标签: c# winforms combobox

我有兴趣使用 DropDownStyle = DropDown 删除组合框的文本选择。
当我添加/删除或关闭 DropPown 时,该项目被选中。
我无法清除所选文本。你知道怎么做吗?

此代码不起作用:

comboBox.SelectionLenght = 0;
comboBox.SelectionStart = comboBox.Text.Legnth;
comboBox.Select(0,0);

我可以看到此行之后的文本突出显示:

selectedComboBox.Items.Add(redCompetitorName);

2 个答案:

答案 0 :(得分:2)

您可以推迟 Select() 方法的执行,在 SelectedIndexChanged 事件处理程序中调用 BeginInvoke()(或 SelectionChangedCommitted,如果您希望这仅在用户手动选择一个项目。

通过推迟执行(此动作在消息循环中排队),Select()动作仅在设置并突出显示ComboBox.Text后才执行。因此,您的命令不会被默认行为覆盖。

private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
{
    // Set the caret to the start of the ComboBox text
    BeginInvoke(new Action(()=> comboBox.Select(0, 0)));

    // OR - set the caret to the end of the text instead
    BeginInvoke(new Action(()=> comboBox.Select(int.MaxValue, 0)));
}

这个概念当然适用于其他情况。
您可以在其他情况下使用此方法,当您需要在 UI 中执行操作时,该操作仅在当前(或已调度 操作的当前序列)完成后执行。< /p>

如果您想要一个更参与的解决方案,以防止组合框中的所有类型的选择突出显示,您可以使用从组合框派生的自定义控件,get the Handle of its Edit Control,使用 {{3}拦截它的消息。覆盖 WndProc 以处理 NativeWindow 并调用 EM_SETSEL 以删除选择(仅当起始位置 > 0 时,否则您可能会陷入具有效果的奇怪自动循环中< /em> 通常被称为 StackOverflow :)

using System.ComponentModel;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;

[DesignerCategory("code")]
public class ComboBoxNoFocus : ComboBox
{
    IntPtr editHandle = IntPtr.Zero;
    private EditNativeWindow editControl = null;

    public ComboBoxNoFocus() { }

    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        editHandle = GetComboBoxEditInternal(this.Handle);
        editControl = new EditNativeWindow(editHandle);
    }


    public class EditNativeWindow : NativeWindow
    {
        private const int EM_SETSEL = 0x0B1;
        public EditNativeWindow() : this(IntPtr.Zero) { }
        public EditNativeWindow(IntPtr handle)
        {
            if (handle != IntPtr.Zero) {
                this.AssignHandle(handle);
            }
        }

        protected override void WndProc(ref Message m)
        {
            switch (m.Msg) {
                case EM_SETSEL:
                    int pos = m.LParam.ToInt32();
                    if (pos > 0) {
                        PostMessage(this.Handle, EM_SETSEL, 0, 0);
                    }
                    return;
                default:
                    // Other operations
                    break;
            }
            base.WndProc(ref m);
        }
    }

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]
    internal static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);

    [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
    internal static extern bool PostMessage(IntPtr hWnd, uint Msg, int wParam, int lParam);

    [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;
        public void Init() => this.cbSize = Marshal.SizeOf<COMBOBOXINFO>();
    }

    internal static IntPtr GetComboBoxEditInternal(IntPtr cboHandle)
    {
        var cbInfo = new COMBOBOXINFO();
        cbInfo.Init();
        GetComboBoxInfo(cboHandle, ref cbInfo);
        return cbInfo.hwndEdit;
    }
}

答案 1 :(得分:1)

在选择新项目后,使用组合框的 SelectedIndexChanged 事件将焦点设置到表单中的另一个控件。

private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
    button1.Focus();
}