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

CheckComboBox 控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.81/5 (54投票s)

1999年11月25日

2分钟阅读

viewsIcon

535100

downloadIcon

16001

带复选框的组合框。

Sample Image

引言

CheckComboBox 控件有什么作用?组合框一直以来都是从几个列表中选择一个项目的途径。如果您需要选择一个或多个项目,您必须使用多选列表框或使用 MFC 的 CCheckListBox。唯一的问题是它会占用对话框或表单中的空间。您需要的是 CCheckComboBox

当我开始开发该控件时,我计划设计一个由静态控件和一个小按钮组成的复合控件。单击按钮后,将显示一个弹出窗口,用户可以在其中选择或取消选择项目。问题是实现它需要太多的代码。我希望外观和感觉就像一个标准的组合框,这在合理的代码量下是不可能实现的。

所以我决定对组合框进行子类化。对组合框进行子类化时的一个问题是,您没有组合框列表部分的窗口句柄,您可以对其进行子类化。您只有组合框的窗口句柄,但这并没有帮助。

诀窍是监听 WM_CTLCOLORLISTBOX 消息。当发送 WM_CTLCOLORLISTBOX 消息时,lParam 包含列表框的窗口句柄。这是进行子类化的时候。

下面的代码展示了如何完成

BEGIN_MESSAGE_MAP(CCheckComboBox, CComboBox)
    ...
    ON_MESSAGE(WM_CTLCOLORLISTBOX, OnCtlColorListBox)
    ...
END_MESSAGE_MAP()

...
LRESULT CCheckComboBox::OnCtlColorListBox(WPARAM wParam, LPARAM lParam) 
{
    // If the listbox hasn't been subclassed yet, do so...
    if (m_hListBox == 0) {
        HWND hWnd = (HWND)lParam;

        if (hWnd != 0 && hWnd != m_hWnd) {
           // Save the listbox handle
           m_hListBox = hWnd;

           // Do the subclassing
           m_pWndProc = (WNDPROC)GetWindowLong(m_hListBox, GWL_WNDPROC);
           SetWindowLong(m_hListBox, GWL_WNDPROC, (LONG)ComboBoxListBoxProc);
        }
    }


    return DefWindowProc(WM_CTLCOLORLISTBOX, wParam, lParam);
}

完成此操作后,其余的就非常简单了。ComboBoxListBoxProc() 例程负责选择/取消选择项目和按键事件。重写的 DrawItem() 例程绘制组合框的列表项和静态部分。如果它是一个项目,它会绘制一个复选标记,然后是文本。如果是静态部分,它会绘制所有选定项目的文本,并用标准列表分隔符分隔。

请注意,CCheckComboBox 必须使用 CBS_DROPDOWNLISTCBS_OWNERDRAWVARIABLE 样式创建。 此外,必须指定 CBS_HASSTRINGS 样式,因为我让组合框处理项目字符串(排序等)。

由于复选标记信息存储在组合框项目数据中,因此应用程序可能无法使用它。将其设置为零将取消选择该项目,否则将选择该项目。但是,使用 GetCheck()SetCheck() 例程代替,因为它们可以正确处理重绘。如果您需要自己的项目数据,则必须自己实现。

使用此控件很容易,因为它派生自 MFC CComboBox。将 CheckComboBox.hCheckComboBox.cpp 添加到您的项目中,并将其用作标准的 CComboBox。在对话框中使用时,只需选择“Control”类别和“Member Variables”页面下的“CCheckComboBox”变量类型,即可声明一个类型为 CCheckComboBox 的对话框中的成员变量,以便您使用。

好吧,我希望有人觉得这有用。至少我发现了。

© . All rights reserved.