MFC中CTreeCtrl类的一些基本用法

来源:互联网 发布:淘宝发布宝贝必填品牌 编辑:程序博客网 时间:2024/06/01 07:36
    最近做课程设计是用到了树形控件,原来对树形控件的用法基本都忘了,这次又重新整合了一下,以加深记忆。
    树形控件可以用于树形的结构,其中有一个根接点(Root)然后下面有许多子结点,而每个子结点上有允许有一个或多个或没有子结点。CTreeCtrl类封装了树形控件的各种操作。在树形控件中每一个结点都有一个HTREEITEM句柄,这个句柄按我的理解其实就是一些十六进制的数,就是用来标识的ID。但是我们通常添加到树形结构的结点都是一些图标或者字符串,这时可以调用:
    CString CTreeCtrl::GetItemText(HTREEITEM hItem);
来获得句柄为hItem的显示字符。同理:
    BOOL CTreeCtrl::SetItemText( HTREEITEM hItem, LPCTSTR lpszItem );
来将句柄为hItem的显示字符设置为lpszItem 。
    一般我们创建了一个树形控件之后就要对这个控件添加结点,CTreeCtrl类提供了一个函数:
    HTREEITEM InsertItem( LPCTSTR lpszItem, HTREEITEM hParent = TVI_ROOT, HTREEITEM hInsertAfter = TVI_LAST );
来帮助我们,这个函数的返回值是新添加结点的HTREEITEM句柄,函数的参数lpszItem是要添加结点的显示字符,hParent代表父结点的句柄,默认为根节点,当前添加的结点会排在hInsertAfter表示的结点的后面,默认是添加在最后。利用这个方法我们可以递归添加无穷的结点。下面的代码会建立一个如下形式的树形结构:
+--- Parent1
    +--- Child1_1
    +--- Child1_2
    +--- Child1_3
+--- Parent2
+--- Parent3

/*假设m_tree为一个CTreeCtrl对象,而且该窗口已经创建*/
    HTREEITEM hItem,hSubItem;
    hItem = m_tree.InsertItem("Parent1",TVI_ROOT);在根结点上添加Parent1
    hSubItem = m_tree.InsertItem("Child1_1",hItem);//在Parent1上添加一个子结点
    hSubItem = m_tree.InsertItem("Child1_2",hItem,hSubItem);//在Parent1上添加一个子结点,排在Child1_1后面
    hSubItem = m_tree.InsertItem("Child1_3",hItem,hSubItem);

    hItem = m_tree.InsertItem("Parent2",TVI_ROOT,hItem);   
    hItem = m_tree.InsertItem("Parent3",TVI_ROOT,hItem); 


此外如果想遍历树可以使用下面的函数:
    HTREEITEM GetRootItem( );得到根结点。
    HTREEITEM GetChildItem( HTREEITEM hItem );得到子结点。
    HTREEITEM GetPrevSiblingItem/GetNextSiblingItem( HTREEITEM hItem );得到指明结点的上/下一个兄弟结点。
    HTREEITEM GetParentItem( HTREEITEM hItem );得到父结点。


    我的程序中利用了这些函数添加了一个三层结构的树,其中考虑了一些结点重复(重复的结点不添加)的问题,发现CTreeCtrl中并没有合适的函数可以使用,于是就自己写了一个,代码如下:

BOOL IsTreeSubItemExist(CTreeCtrl* pTree,HTREEITEM hParent,CString szCurrent)
{
    HTREEITEM hChild=pTree->GetChildItem(hParent);        //得到子结点
    while(hChild!=NULL)            //遍历子结点
    {
        if(pTree->GetItemText(hChild)==szCurrent)
            break;
        hChild=pTree->GetNextSiblingItem(hChild);
    }
    if(hChild==NULL)
        return FALSE;
    else
        return TRUE;
}

这个函数用来确定pTree中句柄为hParent的结点是否存在显示字符为szCurrent的结点,若存在返回真,不存在返回假。

在这个函数的基础上,我又写了一个添加的完整的代码,如下:

void CMyView::UpdateTreeViewCtrl()               
{
    CTreeCtrl* pMyTree=(CTreeCtrl*)this->GetDlgItem(IDC_TREE_MAINALLMSG);
    HTREEITEM hItem;
    HTREEITEM hSubItem;
   
    CElectricDevice* pNextDevice=m_pFirst->m_nextDevice;
    while(pNextDevice!=NULL)
    {
        if(!IsTreeSubItemExist(pMyTree,TVI_ROOT,pNextDevice->m_brand))   
        {
            hItem=pMyTree->InsertItem(pNextDevice->m_brand,TVI_ROOT);
            hSubItem=pMyTree->InsertItem(pNextDevice->m_style,hItem);
            pMyTree->InsertItem(pNextDevice->m_type,hSubItem);
        }
        pNextDevice=pNextDevice->m_nextDevice;
    }

    pNextDevice=m_pFirst->m_nextDevice;
    while(pNextDevice!=NULL)
    {
        hItem=pMyTree->GetChildItem(TVI_ROOT);
        while(hItem!=NULL)
        {
            if(pMyTree->GetItemText(hItem)==pNextDevice->m_brand)
                break;
            hItem=pMyTree->GetNextSiblingItem(hItem);
        }
        if(hItem!=NULL)
        {
            if(!IsTreeSubItemExist(pMyTree,hItem,pNextDevice->m_style))
            {
                hSubItem=pMyTree->InsertItem(pNextDevice->m_style,hItem);
                pMyTree->InsertItem(pNextDevice->m_type,hSubItem);
            }
        }
        pNextDevice=pNextDevice->m_nextDevice;
    }

    pNextDevice=m_pFirst->m_nextDevice;
    while(pNextDevice!=NULL)
    {
        hItem=pMyTree->GetChildItem(TVI_ROOT);
        while(hItem!=NULL)
        {
            HTREEITEM hSubSubItem=pMyTree->GetChildItem(hItem);
            while(hSubSubItem!=NULL)
            {
                if(pMyTree->GetItemText(hItem)==pNextDevice->m_brand &&                                 pMyTree->GetItemText(hSubSubItem)==pNextDevice->m_style)
                {
                    if(!IsTreeSubItemExist(pMyTree,hSubSubItem,pNextDevice->m_type))
                    {
                        pMyTree->InsertItem(pNextDevice->m_type,hSubSubItem);
                    }
                }
                hSubSubItem=pMyTree->GetNextSiblingItem(hSubSubItem);
            }
            hItem=pMyTree->GetNextSiblingItem(hItem);
        }
        pNextDevice=pNextDevice->m_nextDevice;
    }
}

这个函数基本上实现我的目标,但是我觉得在算法上不是很有效率,由于代码很简单我也不介绍了,等有了改进的方法我会再来更新的。

    CTreeCtrl还有很多其他的丰富的方法目前此次也没有用到,就只介绍我用到的这些吧!以后用到之后再来补上!

    这篇文章基本上是原创,部分参考了  csdn论坛:dongle2001的专栏,在此表示感谢!

      



    
原创粉丝点击