区分大小写的组合框






4.38/5 (8投票s)
具有区分大小写搜索功能的 CComboBox(
在组合框中搜索字符串时,搜索始终不区分大小写。我的应用程序需要一个区分大小写的组合框,因此我创建了这个类来实现它。
我本可以使用 CComboBoxEx
来获得一个区分大小写的组合框,但它不是 CComboBox
的直接替换。CComboBoxEx
中没有实现 CComboBox
的常用方法(例如 AddString
)。这意味着为了使用它需要进行大量重写。
如何使用
使用 CComboBoxCS
类非常简单。按照以下步骤将其添加到现有项目中。
- 将源文件(ComboBoxCS.cpp 和 ComboBoxCS.h)放入您希望使用的目录中后,将这些文件添加到您的 Visual Studio 项目中。
- 在资源编辑器中,添加一个组合框到您想要的位置。
- 在类向导中,为您的组合框控件添加一个成员变量,在“类别”列表中选择“控件”,在“变量类型”列表中选择“
CComboBoxCS
”。(如果CComboBoxCS
未出现在列表中,您可能需要删除您的类向导文件(.clw)并重新生成它)。我将假设您的控件变量名为 m_combo。 - 为了使组合框区分大小写,请在您的对话框类中添加一个
WM_INITDIALOG
的处理程序(如果您还没有的话),并向其中添加以下代码:
m_combo.SetCaseSensitiveSearch();
您只需要做这些。
如果您使用许多希望全部区分大小写的组合框,可以通过添加以下内容来设置所有实例的默认值:
m_combo.SetCaseSensitiveSearchDefault();
或者,如果您总是希望此行为,则可以在源代码中更改默认值:
/*static*/ BOOL CListBoxCS::ms_bCaseSensitiveSearchDefault = TRUE;
工作原理
CComboBoxCS
的列表框部分被子类化为 CListBoxCS
,它提供了区分大小写的功能。(请注意,如果您需要一个区分大小写的列表框, CListBoxCS
类可以替代 CListBox
)。为了子类化列表框,有两种方法可用。一种方法(“混乱的方法”)是处理 WM_CTLCOLOR
消息。这是一个标准的(且有充分文档记录的)方法。另一种方法(“干净的方法”)是使用 API 函数 GetComboBoxInfo 来询问组合框的列表控件。干净方法的缺点是它仅在 Win98 或 WinNT 4.0 SP6 或更高版本上可用。代码使用 LoadLibrary/GetProcAddress 来确定该函数是否可用。如果可用,则使用它,否则回退到混乱的方法。
混乱方法的一个问题是,列表框在用户下拉组合框的列表部分之前不会被子类化。这在这里不够好,因为我们需要在进行 FindString
或 FindStringExact
时列表已经被子类化。所以,我们必须作弊。
收到 FindString
、FindStringExact
或 SelectString
消息时,我们检查是否需要子类化列表。如果我们区分大小写且列表尚未子类化,则需要。如果我们不需要,则将消息传递给标准的组合框 Windows 过程。
假设我们需要子类化,然后我们调用函数来下拉组合框的列表部分。这会强制列表(重新)绘制,这会导致将所需的 WM_CTLCOLOR
发送到组合框。
这有一个问题,就是列表框会闪烁一下,然后关闭。为了阻止列表闪烁,我们不能仅仅关闭组合框的重绘,因为这不会影响列表;也不能关闭列表的重绘,因为我们还没有它。我使用的代码会缩小组合框,使其列表框的高度为零像素,然后将其下拉。然后将其的大小调整回原来的位置。所有这些都可以在组合框关闭重绘的情况下完成。
使用干净的方法,我们不会遇到这些问题,可以直接询问组合框列表框的句柄,然后对其进行子类化。这会尽早完成,可能是在用户键入编辑控件时、列表下拉时,或者组合框收到 FindString
/FindStringExact
/SelectString
消息时。
历史
版本 2.2.1 - 2007 年 4 月 20 日
- 更新为可在 VC7 (VS2003) 和 VC8 (VS2005) 中正确构建
版本 2.2 - 2004 年 6 月 23 日
- 将
FindString()
方法重命名为OnFindString()
,因为这阻止了使用标准的CComboBox::FindString
方法 - 在子类化的列表中添加了对拥有者绘制消息的捕获,以确保它们由组合框处理,从而解决使用拥有者绘制的组合框时出现的问题,进而使子类化的列表拥有者绘制
- 使 USER32.DLL 的加载以提供
GetComboBoxInfo()
函数仅发生一次(对于应用程序的整个生命周期),以防止每次子类化组合框时都发生 - 将
CBN_EDITCHANGE
和CBN_DROPDOWN
的处理程序更改为使用ON_CONTROL_REFLECT_EX
,以允许控件的父级也处理它们 - 向
CListBoxCS
添加了LB_SELECTSTRING
的处理程序
版本 2.1 - 2003 年 7 月 9 日
- 更新以支持 Unicode
版本 2 - 2002 年 6 月 12 日
- 新的(干净的)子类化方法 - 使用 API 函数
GetComboBoxInfo()
(如果可用),否则回退到“混乱”的方法 - 添加了对
CB_SELECTSTRING
消息的处理 - 搜索代码的一些小更改
版本 1 - 2001 年 9 月 11 日
- First version.