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

简单的树控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.50/5 (22投票s)

2002年10月29日

3分钟阅读

viewsIcon

262030

downloadIcon

5572

关于更简单地使用 CTreeCtrl 的文章(我认为)

为什么需要新的树控件

首先,市面上有很多自定义树控件,那么为什么还需要这个呢?在我的一项项目中,我需要使用多个树控件来显示不同级别的的数据对象,并且需要处理用户操作。每次,我的树控件都必须根据所选项目以不同的方式做出响应。在这里,我将展示我所拥有的(我重写了一些代码来使用这个自定义控件,并且我相信它现在更易读、易懂)。

工作原理

CSimpleTreeCtrl “简单地”覆盖了MFC的CTreeCtrl类,并提供了一些访问函数来处理它。CSimpleTreeCtrl::TreeCtrlItem用于在树控件中添加新项。您应该编写自己的类(以更好地使用它)并覆盖virtual函数,以便接收窗口消息的通知,例如项目选择、右键单击等。

CSimpleTreeCtrl提供了以下virtual函数

     virtual void          selChanged ( TreeCtrlItem *item ) {} ;
     virtual void          lClick ( TreeCtrlItem *item ) {} ;
     virtual void          lDblClick ( TreeCtrlItem *item ) {} ;
     virtual void          rClick ( TreeCtrlItem *item ) {} ;
     // will be called after three control is created
     virtual void          postCreate ( void ) {} ;

您会注意到,基类与这些函数无关。它只是处理窗口消息并调用virtual函数(我只是厌倦了必须注册我的消息处理函数)。基类还会让CTreeCtrl执行自己的操作,因此每当您收到lClick()时,如果此单击导致当前选择发生更改,您还将收到selChanged()。唯一的区别在于rClick():由于在大多数情况下我希望右键单击更改所选项目,因此我在消息处理程序中处理了这种情况,因此它也会发送一个selChanged()(如果存在选择)。您可以根据需要更改此行为。

对我来说,最有用的部分是CSimpleTreeCtrl::TreeCtrlItem。这个类提供了以下virtual函数

     // will be called on selection
     virtual void          onSelected   ( void ) {} ;
     // will be called for old selected item when there is a new selection (before 
     // onSelected() for new item)
     virtual void          onUnSelected ( void ) {} ;
     // will be called with position in screen coordinates if user right clicks on item
     virtual void          onRClick    ( CPoint pos ) {} ;
     // will be called if user left double clicks on item
     virtual void          onLDblClick ( void ) {} ;
     // will be called after item inserted in tree
     virtual void          postInsert  ( void ) {} ;

它还提供了两个您可能觉得有用的附加函数。感谢 Michael Dunn 和他的文章《使用自定义绘制在列表控件中做一些炫酷的事情》。

     void          setTextColor   ( COLORREF color ) ;
     void          setBkColor     ( COLORREF color ) ;

默认情况下,项目文本的颜色为黑色(RGB(0, 0, 0)),项目背景为白色(RGB(255, 255, 255))。

您可以编写自己的类,只处理所需的virtual函数,如下所示

     class BaseCtrlItem : public CSimpleTreeCtrl::TreeCtrlItem
     {
     public:
          BaseCtrlItem ( CString name, CMyDataClass *myData ) 
               : CSimpleTreeCtrl::TreeCtrlItem ( name ) 
          {
               m_myData = myData ;
          } ;

          virtual ~BaseCtrlItem () {} ;

          virtual void     postInsert ( void ) 
          {
               //You can insert sub items to the tree control if necessary
          } ;

          virtual void     onRClick ( CPoint pos ) 
          {
               //Show popup menu according to your data pointer
          } ;

     protected:
          CMyDataClass *m_myData ;          
     };

如果一个项从树中删除(使用CSimpleTreeCtrlCTreeCtrl函数),相关的CSimpleTreeCtrl::TreeCtrlItem指针也将被移除,因此您无需担心删除项指针。

这个类还有一些可以添加的功能,但我希望保持它尽可能简单。此外,它处理了我项目中的大多数需求。不过,我很乐意听取有关如何在保持简单性的同时添加任何有用功能的建议。

演示应用程序创建一个新的树控件,并以不同的颜色添加一些项。它还处理项的onRClick()函数。您只需将 SimpleTreeCtrl.hSimpleTreeCtrl.cpp 添加到您的项目中即可享受它。头文件应该足够清晰作为文档,如果不够,请告诉我 :-)

已知问题

  1. CSimpleTreeCtrl不会隐藏CTreeCtrl的基础实现,因此用户也可以使用基类功能。但是,这可能会导致一些问题。每当一个CSimpleTreeCtrl::TreeCtrlItem项被添加到树中时,它的指针就会作为项数据添加到CTreeCtrl中。如果您使用HTREEITEM来添加新项并自行设置项数据,CSimpleTreeCtrl将假定用户数据是CSimpleTreeCtrl::TreeCtrlItem或其派生指针。如果没有用户数据,应该不会有问题。
  2. 当树控件收到OnCreate()消息时,将调用CSimpleTreeCtrl::postCreate()。我注意到在某些情况下(根据您如何使用树),该控件未收到此消息。但我没有详细检查。如果您遇到任何问题,请向我发送详细信息。

许可证

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

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

© . All rights reserved.