1. 程式人生 > WINDOWS開發 >Delphi下Treeview控制元件基於節點編號的訪問

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,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,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.