防止 System.Window.Forms.ComboBox 的自动选择行为 (C#)

2024-03-05

背景:

我有一个Forms.ComboBox with a DropDownStyle = DropDown.

我不使用AutoComplete,但我实现了类似的东西,它不仅过滤文本的开头,而且使用正则表达式并显示与输入的文本匹配的所有项目。这很好用。

但是,当我键入匹配项的第一个字母时,ComboBox回到原来的行为并设置DroppedDown = true并自动选择第一个条目并完成文本以匹配所选项目(类似于AutoCompleteMode附加)。我想要的是没有自动选择和自动完成。

到目前为止我发现的是,我必须以某种方式阻止SendMessage() with CB_FINDSTRING被召唤和替换CB_FINDSTRING with CB_FINDSTRINGEXACT (MSDN 链接 http://msdn.microsoft.com/en-us/library/windows/desktop/bb775837(v=vs.85).aspx).

我想我必须扩展 ComboBox 类,但我不确定必须重写哪些方法。我正在使用 C# .NET Framework v3.5。

问题:

  • 我如何延长Windows.Forms.ComboBox防止自动选择行为?

Links:

如何防止下拉组合框中的自动选择(精确匹配除外)? https://stackoverflow.com/questions/16544663/how-can-i-prevent-auto-select-in-combobox-on-drop-down-except-for-exact-matches(没有帮助我)


尝试这个:

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

using Opulos.Core.Win32;

namespace Opulos.Core.UI {

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

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

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

防止 System.Window.Forms.ComboBox 的自动选择行为 (C#) 的相关文章

  • 获取 WSA 错误代码的格式化消息

    我在 win32 C 应用程序中使用winsock2 我将使用 MessageBox 显示可以通过调用 WSAGetLastError 检索的网络错误 我怎样才能做到这一点 我看到 FormatMessage 但我不明白如何使用它 例如 以
  • DataGridView 自动完成组合框列不保留初始单元格离开时的值

    我有一个带有自动完成组合框列的绑定 dataGridView 并且自动完成功能正在工作 只是我观察到一种有点令人恼火的行为 当我第一次在自动完成单元格中键入文本并使用 tabKey 移动到下一个单元格时 我的选择不会保留 我选择的内容将被清
  • 从对象中获取类型正在返回运行时类型[重复]

    这个问题在这里已经有答案了 我有一个简单的功能 public string getType object obj Type type obj getType return type FullName 如果您在运行时创建的字符串对象上使用此函
  • Qml 中的 FileDialog 在发布中不起作用

    我正在与以下项目合作Qt Quick Control 2 当我尝试在调试模式下运行软件时 FileDialog qml 可以完美打开 但是当我将其部署为发布模式时 它无法工作 这是我的代码 import QtQuick 2 4 import
  • 将 CryptoStream 解密为 MemoryStream

    我编写了一个过程 其中文件被加密并上传到 Azure 然后必须解密下载过程 这会失败并出现 填充无效且无法删除 错误 或 要解密的数据长度为无效的 错误 我在网上尝试了很多解决方案 包括C 使用 RijndaelManaged 和 Cryp
  • 如何设置属性选择器的值 Expression>

    我需要使用模式工厂的想法将 Person 类实体中的实体属性 Address 与 FactoryEntities 类中的表达式 linq 相关联 看看这就是我所拥有的并且我想要做的 Address address new Address a
  • C# 中的异步方法如何工作?

    我在我的一些项目中使用异步方法 我喜欢它 因为它使我的应用程序更具可扩展性 但是 我想知道异步方法如何在后台真正工作 NET 或 Windows 如何知道调用已完成 根据我进行的异步调用的数量 我可以看到创建了新线程 但并不总是 为什么 此
  • std::atomic 是否会阻止非原子变量对原子变量进行重新排序

    问题很简单 问 如果我有 settings N STNGS used by many threads std atomic
  • C++ 中的静态虚函数

    我有一个基类和一个派生类 我想更改基函数 同时保持它们静态 因为它们应该作为静态传递给其他函数 我怎样才能做到这一点 ATL 框架通过将基类设为模板 然后让派生类将其类类型作为模板参数传递 从而绕过了无虚拟静态的限制 然后 基类可以在需要时
  • 委托:方法名称预期错误

    我正在尝试让以下简单的委托示例正常工作 根据我从中取出的一本书 应该没问题 但我得到了Method name expected error namespace TestConsoleApp class Program private del
  • 枚举和枚举类之间的区别[重复]

    这个问题在这里已经有答案了 谁能解释一下两者之间的区别 enum Type1 type2 And enum class Type1 type2 我经常使用前者 可能太频繁而没有足够的封装 但我从未使用过第二个例子 Thanks enum A
  • Windows Phone 8.1 应用程序多语言

    我正在使用 Visual Studio 2015 在 SilverLight 中创建 Windows Phone 应用程序 8 1 我正在用英语和阿拉伯语创建多语言应用程序 为此 我在项目中创建了 Strings 文件夹 其中包含 en U
  • 拦截C# HttpClient GetAsync

    我有一个 Web 项目 C MVC5 但没有 WebAPI 和一个简单的 HTTP REST 客户端 该客户端调用外部 REST 服务并获取 accessToken 等 我想检查所有 Get PostAsync 调用对 statusCode
  • 如何使用 GCC 在 C 上编译库?

    我用这些文件创建了一个库pila h and pila c 我编译文件pila c with gcc pila c c这个库运行良好 我已经测试过了 然后我又做了一个图书馆 这个库有文件pila funciones extra h and
  • 初学者友好的方法来获取所有文件和目录的列表

    使用 NET 3 0 我得到了下面的方法 它可以正确返回指定目录的所有文件和目录 以及子目录 的集合 如果可能的话 我想将其简化为仅使用我非常熟悉的结构 具体来说 有以下几点我不太清楚 1 IEnumerable
  • 使用全局 Web API 过滤器属性进行 Unity 依赖注入

    参考这个CodePlex 统一文章 http unity codeplex com discussions 446780我能够使用 WebAPI 控制器获取过滤器属性 如下所示 MyFilterAttribute public class
  • C++ 头文件包含

    我正在开发一个项目 每个头文件都有一个预处理器包含防护 我的包含是这样的 文件 gt 包含 main cpp gt header h 字符 h header h gt 矢量 iostream DataFiles h Character h
  • C# - 平移光标

    我正在 PictureBox 控件中实现大图像的平移 并且设置适当的方向平移光标没有问题 但是 我似乎找不到用于平底锅原点的图像 内部带有箭头的圆圈 我在哪里可以找到它 我觉得image您正在寻找的内容未包含在框架中 每个应用程序都使用自己
  • 如何让c代码执行hex机器代码?

    我想要一个简单的 C 方法能够在 Linux 64 位机器上运行十六进制字节码 这是我的 C 程序 char code x48 x31 xc0 include
  • 如何为单个函数设置 ICC 属性“fp-model precision”,以防止关联优化?

    我正在实施卡汉求和 http en wikipedia org wiki Kahan summation algorithm 在支持 gcc47 gcc48 clang33 icc13 和 icc14 编译的项目中 作为该算法的一部分 我想

随机推荐

  • 请求中的 URL 超出最大重试次数

    我正在尝试获取以下内容应用商店 gt 商业 https itunes apple com in genre ios business id6000 mt 8 import requests from lxml import html pag
  • Crystal Reports 文本截断详细信息部分中的最后一行

    我有一个 Crystal Report 11 文件 它是一封信 第一个详细信息部分包含一个大文本框 其中包含打印日期 地址块和称呼行 每隔一段时间 文本框的最后一行就会被切断 这样就看不到称呼了 这是非常不一致的 因为有时 我为系统中的一个
  • BlackBerry 中的图像按钮

    如何在 BlackBerry 中实现图像按钮 在这里 完整的代码 import net rim device api system Bitmap import net rim device api ui Graphics import ne
  • Python 将 args 转换为 kwargs

    我正在编写一个装饰器 它需要在调用它正在装饰的函数之前调用其他函数 装饰函数可以具有位置参数 但装饰器将调用的函数只能接受关键字参数 有人有一种将位置参数转换为关键字参数的便捷方法吗 我知道我可以获得修饰函数的变量名列表 gt gt gt
  • 正确的 javascript 继承

    我读了很多关于 javascript 中 继承 的文章 其中一些使用new当其他人推荐时Object Create 我读得越多 就越感到困惑 因为似乎存在无数的变体来解决继承问题 有人可以向我展示最受接受的方式 或者事实上的标准 如果有的话
  • 为什么动态更新 DOM 时 html 源不会改变

    我之前发过一个问题jQuery 在 IE 8 和 FF 3 5 8 中设置只读属性不一致 https stackoverflow com questions 2381621 jquery inconsistency in setting r
  • @error 指令不在 Laravel 视图中显示错误

    我正在研究自定义 Laravel 登录实现 我已从控制器返回错误 如下所示 credentials request gt only email password if Auth attempt credentials Authenticat
  • 如何在android上获取处理器编号

    大家好 我想获取android上的处理器编号 我可以这样做吗 int processporNum sysconf SC NPROCESSORS CONF 但每次在我的某些手机上返回值都是1 所以我不确定这个方法是否正确 是否有其他API可以
  • matplotlib 绘图 沿绘图线的标签

    matplotlib 社区的一份 假设我有一条直线 plot 37 45 0 67778 0 67778 k lw 1 2 我可以沿着线而不是在图例中向该线添加标签吗 即 类似于以下内容 但不是等高线图 只是普通的线图 下面是一个例子 只是
  • OpenSSl + PHP如何实现[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我需要在项目中使用 openSSL
  • 如何删除pandas中每组的第一行

    我有一个像这样的数据框 id values 0 1 3 1 1 6 2 1 3 3 2 7 4 2 6 5 2 3 6 2 9 我想根据删除每组的第一行id 结果应该是这样的 id values 1 1 6 2 1 3 4 2 6 5 2
  • 使用 JS 将任何标签内的文本复制到剪贴板[重复]

    这个问题在这里已经有答案了 我需要复制 p 标签内的文本 我尝试使用以下代码 HTML p Text to copy p
  • Subversion 中的合并比 Team Foundation System 中的合并更困难吗?

    我习惯了使用TFS 我的公司现在正在为一个新项目切换到SVN 主要原因是为了更好地将我们的java和 Net代码库合并在同一源代码控制下 我被赋予理解颠覆中的合并是困难的 杰夫提到了这一点 https blog stackoverflow
  • java中的cloneable接口有什么用?

    实现可克隆接口有什么用 因为它是一个标记接口 我总是可以在我的类中创建一个公共 Object clone 方法 可克隆接口的实际用途是什么 那是因为clone 方法抛出CloneNotSupportedException如果你的对象不是Cl
  • 如何调用我们的应用程序并获取来电的详细信息?

    如果我的应用程序中保存了任何号码 并且该用户在我的 iPhone 上呼叫我 那么我想通过屏幕调用我的应用程序 用户可以在屏幕上填写有关该呼叫的信息 例如呼叫持续时间 呼叫者姓名和一些应用程序特定的详细信息 请指导我如何在 iOS 中实现通话
  • 在 C 中声明数组而不指定大小

    当像这样声明一个数组时 int array 1 2 3 4 5 6 我收到一条错误消息 数组类型具有不完整的元素类型 到底是怎么回事 对于N维数组 N gt 0 需要定义N 1维的大小 只能留下一个维度供编译器确定 并且它必须是第一个维度
  • 逐行分割字符串并进行变量化,即将其分配给 GITHUB_OUTPUT - 工作流程

    Github 行动run调用 powershell 返回如下 Powershell返回函数 return psitem Key psitem Value 返回值被分配给 github 操作变量 returnvalue 返回包含一个列表key
  • 使用自定义项目模板在组合框中显示所选项目

    我使用此页面中的代码来设计我的组合框的样式 如何在鼠标悬停时设置组合框背景的样式 https stackoverflow com a 5564151 2848002 我更改了默认项目模板 但现在它们不会出现在所选值区域中 在下图中 您可以看
  • 如何从 XML 文件中删除不可见的垃圾字符

    我想读取一些 xml 文件 当我用记事本 写字板 MS Word 或任何浏览器打开这些文件时 它以其原始形式打开 但是当我尝试用 MS DOS 执行它时 会出现一个看不见的字符 如 被看到 我认为 正在创建一个错误 我发现错误 序言中不允许
  • 防止 System.Window.Forms.ComboBox 的自动选择行为 (C#)

    背景 我有一个Forms ComboBox with a DropDownStyle DropDown 我不使用AutoComplete 但我实现了类似的东西 它不仅过滤文本的开头 而且使用正则表达式并显示与输入的文本匹配的所有项目 这很好