Delphi实现树型结构
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, DB, ADODB; type PNodeInfoEx = ^TNodeInfoEx; TNodeInfoEx = Packed Record NodeID : Integer; ParentID : Integer; NodeType : Integer; ChnNodeTitle : String; ImageIndex: SmallInt; SelectedIndex: SmallInt; end; TForm1 = class(TForm) tv1: TTreeView; btn1: TButton; qry1: TADOQuery; procedure btn1Click(Sender: TObject); procedure FormDestroy(Sender: TObject); private { Private declarations } function StaticBuildTree(TreeView:TTreeView ):Boolean; function AddTreeItem(TreeView:TTreeView; AddNodeInfo:PNodeInfoEx):TTreeNode; function FindTreeItem(TreeView:TTreeView; CurNodeID:integer): TTreeNode; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} function TForm1.StaticBuildTree(TreeView:TTreeView ):Boolean; var AddNodeInfo : PNodeInfoEx; begin Result := False; qry1.LoadFromFile('c:/AdminixTree.xml');//这里以XML文件做为数据源 Treeview.Items.BeginUpdate;//记住:在进行批量添加数据时要使用BeginUpdate,来暂时关闭由于添加数据而触发的某些事件(如OnChange事件等) Treeview.Items.Clear;//清空Treeview try try if qry1.RecordCount >0 then begin qry1.First; while Not qry1.Eof do begin New(AddNodeInfo) ;//生成结构体 AddNodeInfo^.NodeID := qry1.FieldByName('NODE_ID').AsInteger; AddNodeInfo^.ParentID := qry1.FieldByName('PARENT_ID').AsInteger; AddNodeInfo^.NodeType := qry1.FieldByName('NodeType').AsInteger; AddNodeInfo^.ChnNodeTitle := qry1.FieldByName('ChnNodeTitle').AsString; AddNodeInfo^.ImageIndex := qry1.FieldByName('ImageIndex').AsInteger; AddNodeInfo^.SelectedIndex := qry1.FieldByName('SelectedIndex').AsInteger; AddTreeItem(Treeview,AddNodeInfo);//把结构体的指针存到Treeview中 qry1.Next; end; end; except Application.MessageBox('生成树结点失败',MB_ICONSTOP+MB_OK); raise;//向上级抛异常 end; qry1.Close; Result := True; finally Treeview.Items.EndUpdate; end; end; //在加入结点时,应先判断加入的是父结点还是子结点,判断的依据是在已存在的树结点中是否存在该结点的ParentID function TForm1.AddTreeItem(TreeView:TTreeView; AddNodeInfo:PNodeInfoEx):TTreeNode; var ParentNode: TTreeNode; begin ParentNode := FindTreeItem(Treeview,AddNodeInfo^.ParentID); If ParentNode <> nil then Result := Treeview.Items.AddChildObject(ParentNode, Trim(AddNodeInfo.ChnNodeTitle), Pointer(AddNodeInfo)) else Result := Treeview.Items.AddObject(ParentNode, Trim(AddNodeInfo.ChnNodeTitle), Pointer(AddNodeInfo)); if Result<>nil then begin Result.ImageIndex := AddNodeInfo.ImageIndex; Result.SelectedIndex := AddNodeInfo.SelectedIndex; end; end; //这里是判断是否存在其父结点 function TForm1.FindTreeItem(TreeView:TTreeView; CurNodeID:integer): TTreeNode; var i : Integer; begin Result := nil; for i := 0 to Treeview.Items.Count-1 do begin if CurNodeID=PNodeInfoEx(Treeview.Items[i].Data)^.NodeID then begin Result := Treeview.Items[i]; Exit; end; end; end; //生成树结构 procedure TForm1.btn1Click(Sender: TObject); begin StaticBuildTree (tv1) end; //在窗体释放时一定要把树结点中的结构体指针给释放掉,对于在Dispose时为什么要进行强制转型后释放,以前有专门的讲解,在此不在累述 procedure TForm1.FormDestroy(Sender: TObject); var i : Integer; begin for i := 0 to tv1.Items.Count-1 do begin Dispose( PNodeInfoEx(tv1.Items[i].Data) ) end; end; end.
//如何访问树结点? procedure TForm1.tv1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var pNode:TTreeNode; begin pNode:=tv1.GetNodeAt(x,y); if (pNode<>nil) and (Button=mbleft) then ShowMessage(PNodeInfoEx(pNode.Data)^.ChnNodeTitle); end;