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

用于过滤选择的复选框树控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (11投票s)

2003 年 2 月 24 日

2分钟阅读

viewsIcon

127646

downloadIcon

3564

一个 ATL 过滤器控件

Sample Image - maximum width is 600 pixels

引言

一年前,我在文章“增强的 CCheckComboBox”中发布了一个 MFC 控件。 许多读者要求我将此控件制成可从 VB 或 .NET 访问的 COM 组件。 另一个要求是尽可能快速地添加新控件。 我决定创建一个包含一组带有复选框树下拉列表的组合框的 ATL 组件。 这些组合框是动态创建的,并显示在 2、3 或 4 列中。

Using the Code

要使用此代码,首先您需要在 VC++ 6.0 或 VC++ .NET 中构建“QuickFilter”项目。 然后,您可以运行三个演示项目:“Test with VB”、“Test with HTML”和“Test with C#”。

填充第一个组合框的示例:(C#)

    //## INIT Countries 
    QF.set_CheckLabel( 0, "Countries:" );
    QF.set_Field( 0, "Countries.ID" );
    QF.AddFolder( 0, "North America" );
        QF.AddString( 0, "USA", 5, ROOT_LEVEL + 2 );
        QF.AddString( 0, "Canada", 6, ROOT_LEVEL + 2 );
    QF.AddFolder( 0, "Europe" );
        QF.AddString( 0, "UK", 7, ROOT_LEVEL + 2 );
        QF.AddString( 0, "Germany", 8, ROOT_LEVEL + 2 );
        QF.AddString( 0, "Russia", 9, ROOT_LEVEL + 2 );
    QF.AddFolder( 0, "Asia" );
        QF.AddString( 0, "Israel", 10, ROOT_LEVEL + 2 );
    QF.CheckAll( 0, true );

关注点

ComboBox 控件由 EditBoxButtonTreeView 组成。 TreeView 是桌面窗口的子窗口,当用户按下组合框的按钮或编辑框时显示或隐藏(这是设计使然)。 我不再像在之前的文章中那样子类化组合框的父窗口,而是使用鼠标捕获和 LostFocus 事件在需要时隐藏下拉列表。

当用户按下组合框的按钮时,我显示下拉列表,并等待 WM_LBUTTONUP 消息以捕获鼠标。 此时,我知道在我的控件之外单击将必须隐藏下拉列表。 一切似乎都很容易,但存在一个问题:如果鼠标已经捕获,树下拉列表的滚动条将无法正常工作。 为了处理这种情况,只要用户使用滚动条,我们就会释放鼠标捕获,然后再次重新捕获鼠标

LRESULT CCheckTreeCtrl::OnLButtonDown(UINT uMsg, WPARAM wParam, 
                                           LPARAM lParam, BOOL& bHandled)
{
    ...
    //## RELEASE Capture
    if (hWnd == m_hWnd)
        if (GetCapture() == hWnd){
            LRESULT result = ::SendMessage( hWnd, WM_NCHITTEST, NULL, 
                                            MAKELONG(point.x, point.y));
            if ((result == HTVSCROLL) || (result == HTHSCROLL)){
                ::ReleaseCapture();
                m_bScroll = TRUE;
                ::SendMessage( hWnd, WM_NCLBUTTONDOWN, result, 
                               MAKELONG(point.x, point.y));
            }
        }
    ...
}

当用户完成使用滚动条后,将发送 WM_CAPTURECHANGED 消息。 在这里,我们将再次捕获鼠标。

LRESULT CCheckTreeCtrl::OnCaptureChanged(UINT uMsg, WPARAM wParam, 
                                              LPARAM lParam, BOOL& bHandled)
{
    ...
    //## SET Capture
    if (IsWindowVisible())
        if (lParam == NULL)
            if (m_bScroll){
                SetCapture();
                m_bScroll = FALSE;
            }
    ...
}

其余的就非常简单了。 尽情享用吧!

历史

这是第一个版本。

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.