【问题标题】:Builder C++ : TTreeView with checkbox itemsBuilder C++:带有复选框项目的 TreeView
【发布时间】:2015-04-17 14:50:40
【问题描述】:

我需要创建一个带有复选框节点的树视图,如下图:

怎么做?

谢谢!

【问题讨论】:

    标签: checkbox treeview c++builder c++builder-xe5


    【解决方案1】:

    TTreeView 组件本身不支持复选框,但标准 Windows TREEVIEW 控件通过TVS_CHECKBOXES style 支持:

    TVS_CHECKBOXES

    Version 4.70。为树视图控件中的项目启用复选框。仅当图像与项目相关联时才会显示复选框。当设置为此样式时,控件有效地使用DrawFrameControl 创建和设置包含两个图像的状态图像列表。状态图像 1 是未选中的框,状态图像 2 是选中的框。将状态图像设置为零会完全删除该复选框。如需更多信息,请参阅Working with state image indexes

    Version 5.80。即使没有图像与项目关联,也会显示一个复选框。

    一旦使用此样式创建树视图控件,就无法删除该样式。相反,您必须销毁控件并在其位置创建一个新控件。销毁树视图控件不会破坏复选框状态图像列表。你必须明确地销毁它。通过向树视图控件发送TVM_GETIMAGELIST 消息来获取状态图像列表的句柄。然后用ImageList_Destroy销毁图片列表。

    如果要使用此样式,则必须在创建树视图控件之后、填充树之前将 TVS_CHECKBOXES 样式设置为 SetWindowLong。否则,复选框可能会显示为未选中,具体取决于时间问题。

    要将TVS_CHECKBOXES 样式应用于TTreeView 组件,您应该派生一个新组件并覆盖虚拟CreateParams() 方法,例如:

    class TMyTreeView : public TTreeView
    {
    protected:
        virtual void __fastcall CreateParams(TCreateParams &Params);
    };
    
    void __fastcall TMyTreeView::CreateParams(TCreateParams &Params)
    {
        TTreeView::CreateParams(Params);
        Params.Style |= TVS_CHECKBOXES;
    }
    

    要在代码中分配复选框状态,您可以使用TreeView_GetItem()/TreeView_SetItem() 宏根据需要切换节点的状态图像索引。

    另外,一种更灵活的方法是简单地将您自己的TImageList 分配给TTreeView::StateImages 属性并用您想要的任何复选框图像填充它,然后您可以根据需要设置TTreeNode::StateIndex 属性。要对复选框上的用户输入做出反应,请使用 TTreeView::OnClickTTreeView::OnKeyDown 事件相应地切换 TTreeNode::StateIndex

    void __fastcall ToggleTreeNodeCheckBox(TTreeNode *Node)
    {
        if ((Node) && (Node->StateIndex != -1))
        {
            if (Node->StateIndex == MyCheckedStateImageIndex)
                Node->StateIndex = MyUncheckedStateImageIndex;
            else
                Node->StateIndex = MyCheckedStateImageIndex;
        }
    }
    
    void __fastcall TMyForm::TreeView1Click(TObject *Sender)
    {
        TPoint P;
        ::GetCursorPos(&P);
        // or: P = Mouse->CursorPos;
        // or: POINTS pts = MAKEPOINTS(::GetMessagePos()); P = Point(pts.x, pts.y);
        P = TreeView1->ScreenToClient(P);
        if (TreeView1->GetHitTestInfoAt(P.x, P.y).Contains(htOnStateIcon))
            ToggleTreeNodeCheckBox(TreeView1->GetNodeAt(P.x, P.y));
    }
    
    void __fastcall TMyForm1::TreeView1KeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
    {
        if (Key == VK_SPACE)
            ToggleTreeNodeCheckBox(TreeView1->Selected);
    }
    

    【讨论】:

    • 我有这个错误 E2064 Cannot initialize 'const TPoint &' with 'tagPOINT'.. in this instruction "P = TreeView1->ScreenToClient(P);"?!
    • 直到并包括 XE4,TPoint 有一个接受 POINT 作为输入的构造函数。在 XE5 中,他们取出了那个构造函数,我不知道为什么。因此,将P 变量从POINT 更改为TPoint。由于TPoint 仍然派生自POINT&P 仍然可以传递给::GetCursorPos()。或将GetCursorPos(&P) 更改为P = Mouse->CursorPos。我更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2019-02-22
    • 1970-01-01
    • 1970-01-01
    • 2011-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多