winforms 停止ComboBox自动完成功能

6l7fqoea  于 2022-11-16  发布在  其他
关注(0)|答案(1)|浏览(164)

我想阻止任何自动完成的痕迹发生在我的组合框。
是否有可能阻止Windows窗体ComboBox对象自动完成?现在,当我键入某个内容的前三个字符并单击另一个ComboBox以在新字段中键入内容时,第一个ComboBox不会更改并保留这三个键入的字母。但是,如果我调整窗体的大小,则它会尝试自动完成ComboBox(如果有匹配的记录以我键入的文本开始)。另外,ComboBox的this恰好是Anchored: Left, Right。我有一种不好的感觉,停止此行为的唯一方法是将ComboBox子类化,并在resize事件或其他事件中执行一些操作...:/
以下是我认为处理自动完成的唯一属性的设置... x1c 0d1x
注意:当我单击右侧的三个点时,AutoCompleteCustomSource中的“Collection”列表为空。

重现此问题:

1.创建一个窗体并在其上放置一个标准ComboBox控件。然后在其正下方放置另一个ComboBox控件。您不会对第二个ComboBox控件执行任何操作(在本示例中,仅用于使用Tab键定位到第二个控件)。
1.在ComboBox属性中找到Items集合并添加以下内容...

  • 测试123
  • blah 321蛋白
  • 足杆

1.在ComboBox属性中,找到Anchor属性并将其更改为Left, Right
1.执行应用程序。
1.测试1:在ComboBox中键入bl,然后按Tab键转到下一个ComboBox。您不会看到任何变化。
1.测试2:在ComboBox中输入bl,然后拖动窗体的右边使其变宽,从而调整窗体的大小。您将看到ComboBox现在已经自动填充了blah321

xn1cxnb4

xn1cxnb41#

https://stackoverflow.com/a/25696213/1039753找到了我要找的东西!
我想没有办法阻止它,除非子类化或做一个扩展类/方法来做它。我想我应该寻找“自动选择”的时候,我正在寻找的是“自动完成”。知道要搜索什么是关键!这段代码工作得很好,使用它你会做一些像...

ComboBoxAutoSelectEx.AutoSelectOff(ComboBox1);

我也没有看到任何性能影响。它看起来就像魔术一样。我稍微修改了那个答案的代码,添加了所需的结构。

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Windows.Forms;

using Opulos.Core.Win32;

namespace MyAppsNamespace {

    [StructLayout(LayoutKind.Sequential)]
    public struct RECT {
      public int Left;
      public int Top;
      public int Right;
      public int Bottom;
    }

    // Extension class to disable the auto-select behavior when a combobox is in DropDown mode.
    public static class ComboBoxAutoSelectEx {
    
        public static void AutoSelectOff(this ComboBox combo) {
            Data.Register(combo);
        }
    
        public static void AutoSelectOn(this ComboBox combo) {
            Data data = null;
            if (Data.dict.TryGetValue(combo, out data)) {
                data.Dispose();
                Data.dict.Remove(combo);
            }
        }
    
        private class Data {
            // keep a reference to the native windows so they don't get disposed
            internal static Dictionary<ComboBox, Data> dict = new Dictionary<ComboBox, Data>();
    
            // a ComboBox consists of 3 windows (combobox handle, text edit handle and dropdown list handle)
            ComboBox combo;
            NW nwList = null; // handle to the combobox's dropdown list
            NW2 nwEdit = null; // handle to the edit window
    
            internal void Dispose() {
                dict.Remove(this.combo);
                this.nwList.ReleaseHandle();
                this.nwEdit.ReleaseHandle();
            }
    
            public static void Register(ComboBox combo) {
                if (dict.ContainsKey(combo))
                    return; // already registered
    
                Data data = new Data() { combo = combo };
                Action assign = () => {
                    if (dict.ContainsKey(combo))
                        return; // already assigned
    
                    COMBOBOXINFO info = COMBOBOXINFO.GetInfo(combo); // new COMBOBOXINFO();
                    //info.cbSize = Marshal.SizeOf(info);
                    //COMBOBOXINFO2.SendMessageCb(combo.Handle, 0x164, IntPtr.Zero, out info);
    
                    dict[combo] = data;
                    data.nwList = new NW(combo, info.hwndList);
                    data.nwEdit = new NW2(info.hwndEdit);
                };
    
                if (!combo.IsHandleCreated)
                    combo.HandleCreated += delegate { assign(); };
                else
                    assign();
    
                combo.HandleDestroyed += delegate {
                    data.Dispose();
                };
            }
        }
    
        private class NW : NativeWindow {
            ComboBox combo;
            public NW(ComboBox combo, IntPtr handle) {
                this.combo = combo;
                AssignHandle(handle);
            }
    
            private const int LB_FINDSTRING = 0x018F;
            private const int LB_FINDSTRINGEXACT = 0x01A2;
    
            protected override void WndProc(ref Message m) {
                if (m.Msg == LB_FINDSTRING) {
                    m.Msg = LB_FINDSTRINGEXACT;
                }
    
                base.WndProc(ref m);
    
                if (m.Msg == LB_FINDSTRINGEXACT) {
                    String find = Marshal.PtrToStringAuto(m.LParam);
                    for (int i = 0; i < combo.Items.Count; i++) {
                        Object item = combo.Items[i];
                        if (item.Equals(find)) {
                            m.Result = new IntPtr(i);
                            break;
                        }
                    }
                }
            }
        }
    
        private class NW2 : NativeWindow {
            public NW2(IntPtr handle) {
                AssignHandle(handle);
            }
    
            private const int EM_SETSEL = 0x00B1;
            private const int EM_GETSEL = 0x00B0;
    
            protected override void WndProc(ref Message m) {
                if (m.Msg == EM_SETSEL) {
                    // if this code is not here, then the entire combobox text is selected
                    // which looks ugly, especially when there are multiple combo boxes.
                    //
                    // if this method returns immediately, then the caret position is set
                    // to (0, 0). However, it seems that calling EM_GETSEL has a side effect
                    // that the caret position is mostly maintained. Sometimes it slips back
                    // to (0, 0).
                    SendMessage(Handle, EM_GETSEL, IntPtr.Zero, IntPtr.Zero);
                    //int selStart = (sel & 0x00ff);
                    //int selEnd = (sel >> 16) & 0x00ff;
                    //Debug.WriteLine("EM_GETSEL: " + selStart + " nEnd: " + selEnd);
                    return;
                }
                base.WndProc(ref m);
            }
    
            [DllImportAttribute("user32.dll", SetLastError=true)]
            private static extern int SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
        }
    
    }
    
    [StructLayout(LayoutKind.Sequential)]
    public struct COMBOBOXINFO {
        public Int32 cbSize;
        public RECT rcItem;
        public RECT rcButton;
        public int buttonState;
        public IntPtr hwndCombo;
        public IntPtr hwndEdit;
        public IntPtr hwndList;
    
        public static COMBOBOXINFO GetInfo(ComboBox combo) {
            COMBOBOXINFO info = new COMBOBOXINFO();
            info.cbSize = Marshal.SizeOf(info);
            SendMessageCb(combo.Handle, 0x164, IntPtr.Zero, out info);
            return info;
        }
    
        [DllImport("user32.dll", EntryPoint = "SendMessageW", CharSet = CharSet.Unicode)]
        private static extern IntPtr SendMessageCb(IntPtr hWnd, int msg, IntPtr wp, out COMBOBOXINFO lp);
    }
}

相关问题