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.
View Code

 

//如何访问树结点?

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;
View Code

 

你可能感兴趣的:(Delphi)