CTreeCtrl保存与读取(完整功能)

原创 2007年10月12日 14:32:00

-

CTreeCtrl树型控件的确是一个很复杂的控件 特别是在VC++6.0中 它基本上完全靠我们手动写代码来完成它的主要功能.无论新手老手 我相信 要重新写个对CTreeCtrl的操作 一定要看以前自己写的代码才能完成 因为它的操作并不是完全能记住的.

其中 对控件中所有节点的操作 是最主要的.遍历每个节点 取得信息 这是非常重要的 我有在.net中使用过树控件操作很是方便.这里我将我使用树控件的方法写下来 它虽然不完美 但很完整 完成了从新增到删除 到保存到读取的全部操作过程.它将保存的结果存于程序目录下的x.ini文件中 你可以打开它来查看保存的信息.这里不但保存了重新构造树结构的信息也保存了附加信息 可以自由修改.最重要的是 这个示例 能够支持树结构的任何操作 包括换顺序 增加 删除 这些操作不会影响任何节点的ID顺序.节点ID 也许或许需要重点说一下 它保存了你构造的树结构的节点顺序 这并不指序号顺序如果你另一个程序读取了这个结构 引用了序号为2的节点 然后你在程序中 在这个节点之前新增一个节点的话 这个节点的序号就变成3了等到另一个程序再读取的话 就变成引用3了.但在这个示例中 并不是根据序号保存的 而是另一个ID编号 你可以随意操作它的顺序 位置实际的ID并不会改变.


源代码下载

源码中已经有非常详细的注释 这里 我主要说下方法.
新增与删除都是非常简单的 唯一要说的是 新增的方法 我使用了取最小空值的方法 也就是 循环所有节点 取出没有值的序号 新增的节点就使用那个序号也就是说 如果你之前有4个节点 你删除了2号节点 你再新增的时候 ID就为2 而不是5.保存的方法与读取相关联 所以怎么保存决定了如何读取.保存的时候我使用了递归遍历所有节点 每个节点需要保存结构信息 以便以后读取重新构造树结构 否则 你保存为了文件如何能还原以前树的结构?
这里还保存了节点名称 节点序号 节点ID(重要).


保存从这里开始

    UINT fileSum=0;//列表总数
    int layer=1;//层次

    queryTreeNode(m_tree,m_tree.GetRootItem(),fileSum,layer);

    最后还要保存总数

    CString _str;
    _str.Format("%d",fileSum);
    WritePrivateProfileString("INFO","filesum",_str,appPathFile);

 


递归保存m_tree所有节点的操作
void   queryTreeNode(CTreeCtrl& m_tree,HTREEITEM   hTreeItem,UINT& fileSum,int& layer) 

    CString   strNode,_str,_id,_layer;  
    _str.Format("%d",1+fileSum++);
    strNode   =   m_tree.GetItemText(hTreeItem);
    _id.Format("%d",m_tree.GetItemData(hTreeItem));
    _layer.Format("%d",layer);
    WritePrivateProfileString("NODE"+_str,"name",strNode,appPathFile);//保存了节点名称
    WritePrivateProfileString("NODE"+_str,"index",_str,appPathFile);//保存了节点序号
    WritePrivateProfileString("NODE"+_str,"id",_id,appPathFile);//保存了节点编号ID
    WritePrivateProfileString("NODE"+_str,"layer",_layer,appPathFile);//保存了节点结构信息(层)
  
//--------------
    //获取子项
    HTREEITEM hFirstChild   =  m_tree. GetChildItem(hTreeItem);
    //如果子项不为空
    if(hFirstChild!=NULL) 
    {
        layer++;
        queryTreeNode(m_tree,hFirstChild,fileSum,layer);
        layer--;
    }
//--------------
    //获取兄项
    hFirstChild   =  m_tree. GetNextItem(hTreeItem,TVGN_NEXT);
    //如果兄项不为空
    if(hFirstChild!=NULL) 
        queryTreeNode(m_tree,hFirstChild,fileSum,layer); 


}


这是我所试验出最优的保存结构方法 速度与信息的全面性也算是较高的.

 

最存好了结构就像下面这样的 相信能看懂

[NODE1]
name=节点序号:1|节点编号ID:1
index=1
id=1
layer=1
[NODE2]
name=节点序号:2|节点编号ID:2
index=2
id=2
layer=2
[NODE3]
name=节点序号:6|节点编号ID:6
index=3
id=6
layer=3
[NODE4]
name=节点序号:7|节点编号ID:7
index=4
id=7
layer=4
[NODE5]
name=节点序号:3|节点编号ID:3
index=5
id=3
layer=2
[NODE6]
name=节点序号:5|节点编号ID:5
index=6
id=5
layer=3
[NODE7]
name=节点序号:8|节点编号ID:8
index=7
id=8
layer=3
[NODE8]
name=节点序号:4|节点编号ID:4
index=8
id=4
layer=2
[NODE9]
name=最后一个9编号
index=9
id=9
layer=2
[INFO]
filesum=9

 

 

然后就是读取了

 


    char buff[255];
    CString   _layer,strNode,_str;  
    int currLayer=0;//当前层
    int _id=0;
    HTREEITEM m_htreeItem=TVI_ROOT;

//------------------

    int _fileSum=GetPrivateProfileInt("INFO","filesum",NULL,appPathFile);

    for (int i=1;i<=_fileSum;i++)
    {
        _str.Format("%d",i);
        //取得节点信息
        _layer.Format("%d",i);
        GetPrivateProfileString("NODE"+_str,"layer",NULL,buff,256,appPathFile);      
        _layer=atoi(buff);
        GetPrivateProfileString("NODE"+_str,"name",NULL,buff,256,appPathFile);
        strNode=buff;
        //GetPrivateProfileString("NODE"+_str,"index",NULL,buff,256,appPathFile);
        GetPrivateProfileString("NODE"+_str,"id",NULL,buff,256,appPathFile);
        _id=atoi(buff);

 

        //如果在下层
        if (_layer>currLayer)
        {

            m_htreeItem = m_tree.InsertItem(strNode,0,1,m_htreeItem,TVI_LAST);
            m_tree.SetItemData(m_htreeItem,_id);//设置附加数据也就是编号

            currLayer++;
            //如果在同层
        }else if (_layer==currLayer)
        {

            m_htreeItem = m_tree.GetParentItem(m_htreeItem);      
            m_htreeItem = m_tree.InsertItem(strNode,0,1,m_htreeItem,TVI_LAST);
            m_tree.SetItemData(m_htreeItem,_id);//设置附加数据也就是编号

            //如果在上层
        }else if (_layer<currLayer)
        {
            //查找上层节点
            while(_layer!=currLayer)
            {
                m_htreeItem = m_tree.GetParentItem(m_htreeItem);
                currLayer--;
            }


            m_htreeItem =m_tree.GetParentItem(m_htreeItem);
            m_htreeItem=m_tree.InsertItem(strNode,0,1,m_htreeItem,TVI_LAST);
            m_tree.SetItemData(m_htreeItem,_id);//设置附加数据也就是编号

        }

      

    }
  

保存递归的思路应该是这样的 传递节点对象 如果为空 则表示没有节点 直接返回 如果有
1.则判断它接下来是否有子节点 如果有的话 再调用递归查找下面的子节点
2.然后子节点又判断有没有子子节点 如果有 则重覆上面的步骤 如果没有
3.则执行下面的判断是否有兄节点 如果有 则递归 重覆1步骤.
4.如果没有 则返回刚刚的调用 则再执行下面的3步骤判断兄节点
5.如果没有 返回上次调用


读取主要是依靠layer来实现的 先读取节点总数 然后进入循环 循环所有节点
1.从文件中读取第i个记录 然后判断这个记录的层是否大于当前的层(第一层总是0)所以一定大于 更新当前节点对象为新增对象
2.如果等于的话 则在当前节点对象的父节点对象上新增节点 这样 就是与当前节点为同一级了 再更新当前节点对象为新增对象
3.如果大于的话 则需要寻找到与之对应的层节点对象上 这里使用循环判断 然后再重覆2步骤.
4.完成一次判断 就返回再从1开始执行

 


最后还是要说下 下面这些信息 是我认为必要保存的 这才是一个能完成基本功能的结构
name--名称
index--序号(可以没有)
id--数据索引支持
layer--读取结构信息

-

CTreeCtrl常见结构体

基本数据项结构   typedef struct _TV_ITEM {   UINT mask; //结构成员有效性屏蔽位   HTREEITEM hItem; //数据项控制句柄   UINT st...
  • qq1134993111
  • qq1134993111
  • 2013年09月08日 11:23
  • 873

转VC中使用CTreeCtrl实现目录树

这是师姐给偶的寒假任务,前面一直没看,快开学了搞了一天也算实现了要的功能(其实就是修正别人的程序不能实现同步选取功能,选了父目录的话其他子目录也同样处于被选取状态)。程序代码主要来自网络上的VCHel...
  • feihuadao
  • feihuadao
  • 2010年12月02日 01:25
  • 3016

vc++树状控件(TreeCtrl)用法

/////////////////////////添加树状///////////////////////////// HTREEITEM hItem,hChildItem; //定义树状控件的句...
  • lxh1230119
  • lxh1230119
  • 2012年07月04日 20:28
  • 7722

MFC 树形控件CTreeCtrl显示文件路径及文件

在上篇文章中简单讲述了"MFC单文档分割窗口显示图片",但是我想实现的是左边显示图片的路径,右边显示图片的情况,所以这里需要讲述如何使用控件List Control\CListCtrl实现该功能,希望...
  • Eastmount
  • Eastmount
  • 2014年02月13日 01:06
  • 14223

MFC CTreeCtrl 设置每一项Item颜色

1.CTreeCtrlXX继承CTreeCtrl,在CTreeCtrlXX里添加SetItemColor方法和重载OnPaint方法 2.添加消息yings 3.重载树控件#define CTre...
  • u011056389
  • u011056389
  • 2013年11月26日 11:28
  • 3103

MFC制作一个可自由添加删除节点的树(CTreeCtrl)类

微软的MFC提供了强大的界面设计功能,但因为其很多函数过于繁琐,对初学者来说不好上手,而我自己在学习过程中也碰到了很多问题,查了很多文章,在此要特地感谢鸡琢米以及各位在CSDN上些小教程的各位前辈大佬...
  • zhuzexujiaxing
  • zhuzexujiaxing
  • 2017年04月23日 10:01
  • 1441

MFC CListBox及CTreeCtrl具有复选框功能

  • 2015年12月07日 19:54
  • 4.92MB
  • 下载

CTreeCtrl Class Windows 公共树视图控件的功能。

成员 公共构造函数 名称 说明 CTreeCtrl::CTreeCtrl 构造 CTreeCtrl 对象。 公共方法 名称 描述 CTreeCtrl::Create 创建的树视图控件,并将其附加到CT...
  • huninglei3333
  • huninglei3333
  • 2017年03月21日 17:41
  • 201

CTreeCtrl 节点支持拖拽功能

1、首先,从CTreeCtrl派生一个类CXTreeCtrl。 2、此类需处理以下问题: a、基本拖动实现; b、处理无意拖动; c、能处理拖动过程中滚动问题; d、拖动过程中节点会智能展开...
  • chaozi2008
  • chaozi2008
  • 2013年03月29日 15:57
  • 3443

如何使用JFileChooser 的showSaveDialog()方法--实现保存文件功能?(完整)

如何使用JFileChooser 的showSaveDialog()方法--实现保存文件功能? JFileChooser的 showSaveDialog()方法,可以打开一个保存文件的对话框,可具体...
  • ljheee
  • ljheee
  • 2016年04月04日 20:05
  • 3898
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:CTreeCtrl保存与读取(完整功能)
举报原因:
原因补充:

(最多只允许输入30个字)