zoukankan      html  css  js  c++  java
  • Delphi下Treeview控件基于节点编号的访问

    有时我们需要保存和重建treeview控件,本文提供一种方法,通过以树结构节点的编号访问树结构,该控件主要提供的方法如下: 
    function GetGlobeNumCode(inNode:TTreeNode):String;
    功能:返回当前节点的编号,编号规则见源码内说明。
    function LocatOrGenerateNode(inNumCode:String):TTreeNode;
    功能:以编号返回节点,假如节点的父节点和它的前继兄弟节点不存在,该方法会创建它们,名称为''''Temp'''',当然假如已经存在,就不执行创建工作。
    通过以上两个函数,这样我们就可以不加限制的创建和访问节点。该控件在我以前开发的,现在提供给大家做一个参考,希望能对你有帮助。

    源码:
    // ***********************************************
    //
    // 用于实现对TreeView控件的树结构的保存和重建
    // 编写该控件主要用于实现对行政文件等具有树的层次结构的对象
    // 实现保存和显示
    // 节点编号规则:
    // ***** ->1
    // ***** ->1.1
    // ***** ->1.1.1
    // ***** ->1.2
    // 作者:Jack
    // 最后修改日期:2002-12-24
    //
    // **********************************************
    unit CtrlTree;

    interface

    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    ComCtrls;

    type
    TCtrlTree = class(TTreeView)
    private
    { Private declarations }
    function GetPosAtBound(inString:String;inStart:Integer):Integer;
    function GetTheLastPointPos(inString:String):Integer;
    protected
    { Protected declarations }
    public
    { Public declarations }
    function GetNumInSameLevel(inNode:TTreeNode):Integer;
    function GetGlobeNumCode(inNode:TTreeNode):String;
    function GetParent(inNumCode:String):TTreeNode;
    function LocateNodeInLevel(parNode:TTReeNode;LevelCode:integer):TTReeNode;
    published
    { Published declarations }
    function LocatOrGenerateNode(inNumCode:String):TTreeNode;
    function InsertAsFinalChild(inString:String;inNode:TTreeNode):TTReeNode;
    function InsertAsPreviousSibling(inString:String;inNode:TTreeNode):TTReeNode;
    end;

    procedure Register;

    implementation

    procedure Register;
    begin
    RegisterComponents(''''Standard'''', [TCtrlTree]);
    end;

    { TCtrTree }

    function TCtrlTree.GetNumInSameLevel(inNode: TTreeNode): integer;
    {功能:产生已存在节点在兄弟节点层中对应的编号,从1起编
    入口参数:inCode:TTreeNode节点
    返回:同层编号
    }
    var
    i:integer;
    tmp:TTreeNode;
    begin
    i:=0;
    tmp:=inNode;
    while tmp<>nil do
    begin
    tmp:=tmp.getPrevSibling;
    i:=i 1;
    end;
    Result:=i;
    end;

    function TCtrlTree.GetGlobeNumCode(inNode: TTreeNode): string;
    {功能:产生已存在节点对应的全局编号
    入口参数:inCode:TTreeNode节点
    返回:全局编号
    }
    var
    nocode:string;
    tmp:TTreeNode;
    begin
    tmp:=inNode;
    nocode:=IntToStr(GetNumInSameLevel(tmp));
    while tmp.Level<>0 do
    begin
    tmp:=tmp.Parent;
    nocode:=inttostr(GetNumInSameLevel(tmp)) ''''.'''' nocode;
    end;
    Result:=nocode;
    end;

    function TCtrlTree.LocatOrGenerateNode(inNumCode: String): TTreeNode;
    {功能:根据提供的全局编号进行定位,如路径不全,则创建路径
    在定位过程产生的节点的Text为Temp
    最终返回对应于全局编号的子节点
    入口参数:inNumCode:String为全局编号
    返回:全局编号对应的字节点
    }
    var
    i,j:Cardinal;
    NumInLevel:integer;
    tmp:TTreeNode;
    par:TTreeNode;
    begin
    tmp:=nil;
    i:=1;
    while i<=StrLen(PChar(inNumCode)) do
    begin
    //得到下一个点号的开始位
    j:=GetPosAtBound(inNumCode,i);
    //得到在兄弟节点中的排行数
    NumInLevel:=StrToInt(Copy(inNumCode,i,j-i 1));
    //定位父节点
    par:=GetParent(Copy(inNumCode,1,j));
    //得到对应的节点
    tmp:=LocateNodeInLevel(par,numInLevel);
    i:=j 2;
    end;
    Result:=tmp;
    end;

    function TCtrlTree.GetParent(inNumCode: String): TTreeNode;
    {功能:根据提供的全局编号找到对应的父节点
    如果是第一层的节点,则父节点为nil
    入口参数:inNumCode:String为全局编号
    返回:全局编号对应的父节点
    }
    var
    GoStep:integer;
    i:integer;
    j:integer;
    k:integer;
    SearChInNode:TTReeNode;
    ReturnNode:TTReeNode;
    begin
    //是第一层节点,返回nil;
    k:=GetTheLastPointPos(inNumCode);
    if k=0 then
    begin
    Result:=nil;
    Exit;
    end;
    //是第二层或第二层以上节点
    i:=1;
    SearchInNode:=Items.GetFirstNode;
    while i < GetTheLastPointPos(inNumCode) do
    begin
    j:=GetPosAtBound(inNumCode,i);
    GoStep:=StrToInt(Copy(inNumCode,i,j-i 1));
    if i=1 then //在第一层节点中搜索
    begin
    ReturnNode:=SearchInNode;
    for k:=1 to GoStep-1 do
    ReturnNode:=ReturnNode.getNextSibling;
    end 

    else //在第二层或第二层以上节点中搜索
    begin
    GoStep:=StrToInt(Copy(inNumCode,i,j-i 1));
    ReturnNode:=SearchInNode.Item[GoStep-1];
    end;
    SearchInNode:=ReturnNode;
    i:=j 2
    end;
    Result:=SearchInNode;
    end;

    function TCtrlTree.LocateNodeInLevel(parNode: TTReeNode;LevelCode: integer): TTReeNode;
    {功能:根据父节点以及在兄弟节点中的编号找到对应的节点
    如果要创建兄弟及自己,则新创建的节点的Text为Temp
    入口参数:parNode: TTReeNode为父节点
    LevelCode: integer为编号
    返回:在parNode中编号为LevelCode的孩子节点
    }
    var
    i:integer;
    j:integer;
    tmp:TTreeNode;
    tmps:TTreeNode;
    begin
    //父节点为空,是第一层节点
    tmp:=nil;
    if parNode=nil then
    begin
    i:=1;
    tmps:=Items.GetFirstNode;
    while (tmps<>nil) and (i<=LevelCode) do
    begin
    tmp:=tmps;
    tmps:=tmps.getNextSibling;
    i:=i 1;
    end;
    i:=i-1;
    for j:=1 to LevelCode-i do
    tmp:=Items.AddChild(nil,''''Temp'''');
    Result:=tmp;
    end
    else //父节点不为空,正常处理
    begin
    if parNode.Count<LevelCode then
    for i:= 1 to LevelCode-parNode.Count do
    Items.AddChild(parNode,''''Temp'''');
    Result:=parNode.Item[LevelCode-1];
    end;
    end;

    function TCtrlTree.GetPosAtBound(inString: String;inStart:Integer): Integer;
    {功能:根据起始位置找到下一个''''.''''的前一个位置
    入口参数:inString: String节点编号
    inStart: Integer当前处理层次的起始位置
    返回:当前处理层次的结束位置
    }
    var
    tmp:Char;
    pos:integer;
    begin
    pos:=inStart 1;
    while pos <= Integer(StrLen(PChar(inString))) do
    begin
    tmp:=inString[pos];
    if tmp=''''.'''' then
    Break
    else
    pos:=pos 1;
    end;
    Result:=pos-1;
    end;

    function TCtrlTree.GetTheLastPointPos(inString: String): Integer;
    {功能:找到编号中最后的''''.''''的位置
    入口参数:inString: String为节点编号
    返回:节点编号中最后的''''.''''的位置
    }
    var
    tmp:Char;
    pos:integer;
    begin
    pos:=Integer(StrLen(PChar(inString)));
    while pos>=1 do
    begin
    tmp:=inString[pos];
    if tmp=''''.'''' then
    Break
    else
    pos:=pos-1;
    end;
    Result:=pos;
    end;

    function TCtrlTree.InsertAsFinalChild(inString: String; inNode: TTreeNode):TTReeNode;
    {功能:为当前节点插入一个孩子节点,位置为最后
    入口参数:inString: String为节点编号为待插入节点的字符串
    inNode: TTreeNode,当前节点
    }
    begin
    Result:=Items.AddChild(inNode,inString);
    end;

    function TCtrlTree.InsertAsPreviousSibling(inString: String;
    inNode: TTreeNode):TTReeNode;
    {功能:为当前节点插入一个前导的兄弟节点
    入口参数:inString: String为节点编号为待插入节点的字符串
    inNode: TTreeNode,当前节点
    }
    begin
    Result:=Items.AddChildFirst(inNode,inString);
    end;

    end.

  • 相关阅读:
    java多线程基础(一)
    重构总体思路
    【Gearman学习笔记】分布式处理入门
    virtualbox安装提示出现严重错误解决办法
    驱动程序vmci.sys版本不正确。请尝试重新安装 VMware
    Gearman任务分布系统部署windows平台_使用Cygwin
    Fatal error: Class 'GearmanClient' not found解决方法
    header('Content-type:text/html;charset = utf-8');出现中文乱码
    heredoc和nowdoc的区别
    SELECT INTO 和 INSERT INTO SELECT 两种表复制语句
  • 原文地址:https://www.cnblogs.com/jijm123/p/11377378.html
Copyright © 2011-2022 走看看