65.9K
CodeProject 正在变化。 阅读更多。
Home

区分大小写的组合框

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.38/5 (8投票s)

2001 年 9 月 11 日

CPOL

5分钟阅读

viewsIcon

178496

downloadIcon

3092

具有区分大小写搜索功能的 CComboBox(和 CListBox)。

ComboBoxCS Demo

在组合框中搜索字符串时,搜索始终不区分大小写。我的应用程序需要一个区分大小写的组合框,因此我创建了这个类来实现它。

我本可以使用 CComboBoxEx 来获得一个区分大小写的组合框,但它不是 CComboBox 的直接替换。CComboBoxEx 中没有实现 CComboBox 的常用方法(例如 AddString)。这意味着为了使用它需要进行大量重写。

如何使用

使用 CComboBoxCS 类非常简单。按照以下步骤将其添加到现有项目中。

  1. 将源文件(ComboBoxCS.cpp 和 ComboBoxCS.h)放入您希望使用的目录中后,将这些文件添加到您的 Visual Studio 项目中。
  2. 在资源编辑器中,添加一个组合框到您想要的位置。
  3. 在类向导中,为您的组合框控件添加一个成员变量,在“类别”列表中选择“控件”,在“变量类型”列表中选择“CComboBoxCS”。(如果 CComboBoxCS 未出现在列表中,您可能需要删除您的类向导文件(.clw)并重新生成它)。我将假设您的控件变量名为 m_combo
  4. 为了使组合框区分大小写,请在您的对话框类中添加一个 WM_INITDIALOG 的处理程序(如果您还没有的话),并向其中添加以下代码:
  5. 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 来确定该函数是否可用。如果可用,则使用它,否则回退到混乱的方法。

混乱方法的一个问题是,列表框在用户下拉组合框的列表部分之前不会被子类化。这在这里不够好,因为我们需要在进行 FindStringFindStringExact 时列表已经被子类化。所以,我们必须作弊。

收到 FindStringFindStringExactSelectString 消息时,我们检查是否需要子类化列表。如果我们区分大小写且列表尚未子类化,则需要。如果我们不需要,则将消息传递给标准的组合框 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_EDITCHANGECBN_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.
© . All rights reserved.