操作TreeView(咏南工作室)
阅读原文时间:2023年07月13日阅读:1

{*******************************************************}
{                                                       }
{       操作TreeView                                    }
{                                                       }
{       版权所有 (C) 2008 咏南工作室                    }
{                                                       }
{*******************************************************}

//==============================================================================
// 本单元实现了TreeView与数据的关联,各方法形参如下:
//
//            AId:为自增字段,用于标识节点的编号。
//            AParentId:用来表示当前节点的父节点。
//            ACaption:用来表示在树中所要显示的内容。
//==============================================================================

unit dbtree;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, ComCtrls, DB, ADODB;

{-------------------------------------------------------------------------------
  过程名:    MakeTree
  说明:      创建树
  作者:      cxg
  日期:      2008.08.21
  参数:      Query: TADOQuery; TableName: string; TreeView: TTreeView;AParentId,AId:string
  返回值:    无
-------------------------------------------------------------------------------}
procedure MakeTree(Query: TADOQuery; TableName: string; TreeView: TTreeView;AParentId,AId:string);

{-------------------------------------------------------------------------------
  过程名:    AddNode
  说明:     增加树的节点
  作者:      cxg
  日期:      2004.12.07
  参数:      Query: TADOQuery; TreeView: TTreeView
  参数说明: Query:相关联的数据库;TreeView: 所使用的树
  返回值:    无
-------------------------------------------------------------------------------}
procedure AddNode(Query: TADOQuery; TreeView: TTreeView;AParentId,ACaption:string);

{-------------------------------------------------------------------------------
  过程名:    AddChildNode
  说明:     增加树的子节点
  作者:      cxg
  日期:      2004.12.07
  参数:      Query: TADOQuery; TreeView: TTreeView
  参数说明: Query:相关联的数据库;TreeView: 所使用的树
  返回值:    无
-------------------------------------------------------------------------------}
procedure AddChildNode(Query: TADOQuery; TreeView: TTreeView;AParentId,AId,ACaption:string);
{-------------------------------------------------------------------------------
  过程名:    AddTreeNode
  说明:     增加节点(内部使用的过程)
  作者:      cxg
  日期:      2004.12.07
  参数:      Query: TADOQuery; TreeView: TTreeView; bj: boolean = false
  参数说明: Query:相关联的数据库;TreeView: 所使用的树;bj:是否将焦点移到当前选择的节点
  返回值:    无
-------------------------------------------------------------------------------}
procedure AddTreeNode(Query: TADOQuery; TreeView: TTreeView; bj: boolean = false);

{-------------------------------------------------------------------------------
  过程名:    DelTree
  说明:     删除节点(包括删除本节点下的所有子节点)
  作者:      cxg
  日期:      2004.12.07
  参数:      query: TAdoQuery; TreeView: TTreeView
  参数说明: Query:相关联的数据库;TreeView: 所使用的树
  返回值:    无
-------------------------------------------------------------------------------}
procedure deltree(query: TAdoQuery; TreeView: TTreeView;AID:string);

{-------------------------------------------------------------------------------
  过程名:    Treechange
  说明:     在树中选择了一个节点,将数据库的游标移动到所选择的节点所对应记录
  作者:      cxg
  日期:      2004.12.07
  参数:      query: TADOQuery; node: TTreenode
  参数说明: Query:相关联的数据库;TreeView: 所使用的树
  返回值:    无
-------------------------------------------------------------------------------}
procedure Treechange(query: TADOQuery; node: TTreenode);

{-------------------------------------------------------------------------------
  过程名:    Treeedit
  说明:     树中的节点内容已经作了修改,将所修改的内容更新回数据库
  作者:      cxg
  日期:      2004.12.07
  参数:      query: TADOQuery; text: string
  参数说明: Query:相关联的数据库;TreeView: 所使用的树
  返回值:    无
-------------------------------------------------------------------------------}
procedure TreeEdit(query: TADOQuery; text: string;ACaption:string);

{-------------------------------------------------------------------------------
  过程名:    treeselect
  说明:     数据库中的游标已经移动,将焦点移到树中对应的节点
  作者:      cxg
  日期:      2004.12.07
  参数:      query: Tadoquery; TreeView: TTreeView
  参数说明: Query:相关联的数据库;TreeView: 所使用的树
  返回值:    无
-------------------------------------------------------------------------------}
procedure treeselect(query: Tadoquery; TreeView: TTreeView;AId:string);

{-------------------------------------------------------------------------------
  函数名:    TreeFind
  说明:     找出给定的内容,并移动数据库中的游标,同时将焦点移到树中对应的节点
  作者:      cxg
  日期:      2004.12.07
  参数:      TreeView: TTreeView; text: string
  参数说明: TreeView: 所使用的树 text: 要查找的内容
  返回值:    True:找到  False:找不到
-------------------------------------------------------------------------------}
function TreeFind(TreeView: TTreeView; text: string): boolean;

implementation

var
  List: TStringList; //用于记录各个id及其在树中所对应的节点,从而实现快速查找

procedure MakeTree(Query: TADOQuery; TableName: string; TreeView: TTreeView;AParentId,AId:string);
begin
  TreeView.Items.BeginUpdate;
  list.Clear;
  TreeView.items.clear;
  if query.Active then query.Close;
  Query.SQL.Text := 'SELECT * FROM ' + TableName + ' ORDER BY '+AParentId+','+AId;
  Query.Open;
  query.DisableControls;
  TreeView.Items.Clear;
  list.Clear;
  List.Sorted := True;
  query.First;
  while not Query.Eof do
  begin
    addtreenode(Query, TreeView); //依次增加所有的节点
    Query.Next;
  end;
  TreeView.Items.EndUpdate;
  query.EnableControls;
  if treeview.Items.Count < 1 then exit;
  treeview.Select(treeview.Items.Item[0]);
  treeview.SetFocus;
end;

procedure addtreenode(Query: TADOQuery; TreeView: TTreeView; bj: boolean = false);
var
  index: integer;
  Node: TTreeNode;
begin
  if Query.FieldByName('PID').AsInteger = 0 then { ParentID=0,顶层节点 }
    Node := TreeView.Items.AddChildObject(nil, Query.FieldByName('CAPTION').AsString, query.GetBookmark)
//增加节点,并将本节点所对应的记录标签数据放到节点所提供的附加数据中
  else
  begin
    Index := List.IndexOf(Query.FieldByName('PID').AsString);
    Node := TreeView.Items.AddChildObjectFirst(TTreeNode(List.Objects[Index]),
      Query.FieldByName('CAPTION').AsString, query.GetBookmark);
//增加子节点,并将本节点所对应的记录标签数据放到节点所提供的附加数据中
  end;
//增加当前节点的信息到列表中,以实现在列表中快速查找节点的功能。
  List.AddObject(Query.FieldByName('ID').AsString, Node);
  if bj then
  begin
    treeview.Select(node);
    treeview.SetFocus;
  end;
end;

procedure deltree(query: TAdoQuery; TreeView: TTreeView;AID:string);
var
  node: TTreenode;
  //删除当前选择的节点下的所有节点(不删除当前选择的节点)
  procedure delnode(node: TTreenode);
  var
    i: integer;
    childnode: TTreenode;
  begin
    for i := 0 to node.Count - 1 do
    begin
      childnode := node.Item[i];                                   //取当前节点下的所有节点
      query.GotoBookmark(childnode.Data);                          //移到节点所对应的记录
      list.Delete(list.IndexOf(query.FieldByName(AID).AsString)); //删除列表中的数据
      query.Delete;                                                //删除对应的记录
      if node.HasChildren then delnode(childnode);                 //有子节点则递归直到所有的数据删除完毕
    end;
  end;

begin
  node := treeview.Selected;
  if node = nil then exit;
//删除当前选择的节点下的所有节点(不删除当前选择的节点)
  delnode(node);
//删除当前选择的节点
  query.GotoBookmark(node.Data);
  list.Delete(list.IndexOf(query.FieldByName(AID).AsString));
  query.Delete;
  node.Delete;
  TreeView.SetFocus;
end;

procedure AddChildNode(Query: TADOQuery; TreeView: TTreeView;AParentId,AId,ACaption:string);
var
  id: integer;
begin
  id := query.FieldByName(AId).AsInteger; //记下当前的节点编号
  query.Append;
  query.FieldByName(AParentId).AsInteger := id; //新增加的子节点的父节点编号即为id
  query.FieldByName(ACaption).AsString := '新子节点';
  query.post;
  addtreenode(query, treeview, true);
end;

procedure AddNode(Query: TADOQuery; TreeView: TTreeView;AParentId,ACaption:string);
var
  pid: integer;
begin
  pid := query.FieldByName(AParentId).AsInteger; //记下当前节点的父节点编号
  query.Append;
  query.FieldByName(AParentId).AsInteger := pid; //新增加的子节点的父节点编号即为pid
  query.FieldByName(ACaption).AsString := '新节点';
  query.post;
  addtreenode(query, treeview, true);
end;

procedure Treechange(query: TADOQuery; node: TTreenode);
begin
  query.GotoBookmark(node.Data);
end;

procedure TreeEdit(query: TADOQuery; text: string;ACaption:string);
begin
  query.Edit;
  query.FieldByName(ACaption).AsString := text;
  query.post;
end;

procedure treeselect(query: Tadoquery; TreeView: TTreeView;AId:string);
var
  index: integer;
  Node: TTreeNode;
begin
  Index := List.IndexOf(Query.FieldByName(AId).AsString);
  Node := TTreeNode(List.Objects[Index]);
  treeview.Selected := Node;
  treeview.SetFocus;
end;

function TreeFind(TreeView: TTreeView; text: string): boolean;
var
  i: integer;
begin
  Result := false;
  for i := 0 to treeview.Items.Count - 1 do
  begin
    if treeview.Items.Item[i].Text = text then
    begin
      treeview.Select(treeview.Items.Item[i]);
      treeview.SetFocus;
      Result := true;
      exit;
    end;
  end;
end;

initialization
  List := TStringList.Create;

finalization
  list.Free;

end.

//调用演示(鼠标拖放移动节点)---------------------------------------------

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  DB, ADODB, StdCtrls, ExtCtrls, Grids, DBGrids, ComCtrls, dialogs;

type
  TForm1 = class(TForm)
    TreeView1: TTreeView;
    DBGrid1: TDBGrid;
    Panel1: TPanel;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Splitter1: TSplitter;
    Splitter2: TSplitter;
    btn2: TButton;
    Button4: TButton;
    Edit1: TEdit;
    ADOQuery: TADOQuery;
    ds1: TDataSource;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
    procedure Button3Click(Sender: TObject);
    procedure TreeView1Edited(Sender: TObject; Node: TTreeNode; var S: string);
    procedure btn2Click(Sender: TObject);
    procedure DBGrid1MouseUp(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure Button4Click(Sender: TObject);
    procedure TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
      State: TDragState; var Accept: Boolean);
    procedure TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
  private
     { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses dbtree;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  MakeTree(ADOQuery, 'dir', TreeView1,'pid','id');  //创建树
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  addnode(adoquery, treeview1,'pid','caption');           //增加节点
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  addchildnode(adoquery, treeview1,'pid','id','caption');       //增加子节点
end;

procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
begin
  treechange(adoquery, node);
end;

procedure TForm1.TreeView1Edited(Sender: TObject; Node: TTreeNode;
  var S: string);
begin
  Treeedit(adoquery, s, 'caption');
end;

procedure TForm1.btn2Click(Sender: TObject);
begin
  deltree(adoquery, treeview1,'id');          //删除树
end;

procedure TForm1.DBGrid1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  treeselect(adoquery, treeview1,'id');
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  if not TreeFind(treeview1,edit1.text) then
    showmessage('找不到。');
end;

procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  Accept := False ;
  if (source is TTreeView) or (source is TListview) then
    Accept := true ;
end;

procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
  tSrcNode ,tDesNode: TTreeNode ;
  tSrcID ,tDesID : Integer ;
  sSql : String ;
  lSrcItem : TListItem ;
  DestNodeId:string;
begin
  tSrcID := 0 ;tDesID := 0 ;

tDesNode := TTreeview(Sender).GetNodeAt(X,Y);
  Treechange(ADOQuery,tDesNode);
  DestNodeId:=ADOQuery.FieldValues['id'];

if Source is TTreeview then
  begin
    TTreeview(Sender).Items.BeginUpdate;

tSrcNode := TTreeview(Source).Selected ;
    tSrcNode.Moveto(tDesNode,naAddChild);
    Treechange(ADOQuery,tSrcNode);
    ADOQuery.Edit;
    ADOQuery.FieldValues['pid']:=DestNodeId;
    ADOQuery.Post;

TTreeview(Sender).Items.EndUpdate;
  end
end;

end.

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章