interface uses Windows, Messages, SysUtils, Variants, Classes, ComCtrls, DB, ADODB, TreeFillThrd; //注意 type TTreeUtils = class TreeView: TTreeView; NData: TNodeData; Conn: TADOConnection; Query: TADOQuery; constructor Create(ATree: TTreeView; AConn: TADOConnection; ATableName: string; AFieldIndex: string = 'ID'; AFieldPID: string = 'PID'; AFieldCaption: string = 'Caption'; ARootText: string = '我的目录'); destructor Destroy; private TableName: string; FieldIndex: string; FieldPID: string; FieldCaption: string; RootText: string; sqlStr, errStr: string; function getMaxIndex: integer; function execSQL(sqlStr: string; var errMsg: string): boolean; public //按照节点在数据库中的编号查找节点 function FindTreeNode(Tree: TTreeView; Index: integer): TTreeNode; //删除子树 function DeleteTree(Node: TTreeNode): Boolean; //查找节点在数据库中的数据 function getTreeNodeData(TreeNode: TTreeNode): TNodeData; function getSelNodeIndex: integer; function getSelNodeCaption: string; //添加节点 function AddNode(ACaption: string = '新节点'; ANode: TTreeNode = nil): Boolean; function AddChildNode(ACaption: string = '新节点'; ANode: TTreeNode = nil): Boolean; //修改节点 function ModifyNodeCaption(NewCaption: string; Node: TTreeNode): boolean; function ModifyNodePID(PID: integer; Node: TTreeNode): boolean; //填充节点 procedure FillTree; end;
implementation //-------------------------------------------------------------- constructor TTreeUtils.Create(ATree: TTreeView; AConn: TADOConnection; ATableName: string; AFieldIndex: string = 'ID'; AFieldPID: string = 'PID'; AFieldCaption: string = 'Caption'; ARootText: string = '我的目录'); begin TreeView := ATree; Conn := AConn; TableName := ATableName; FieldIndex := AFieldIndex; FieldPID := AFieldPID; FieldCaption := AFieldCaption; RootText := ARootText; Query := TADOQuery.Create(nil); Query.Connection := Conn; end; //-------------------------------------------------------------- destructor TTreeUtils.Destroy; begin Query.Free; inherited Destroy; end; //-------------------------------------------------------------- function TTreeUtils.FindTreeNode(Tree: TTreeView; Index: integer): TTreeNode; var i: integer; begin Result := nil; for i := 0 to Tree.Items.Count - 1 do if PNodeData(Tree.Items.Item[i].Data)^.Index = Index then Result := Tree.Items.Item[i]; end; //-------------------------------------------------------------- function TTreeUtils.DeleteTree(Node: TTreeNode): Boolean; function DelTableFromIndex(index: integer): boolean; var sqlStr: string; errSTr: string; begin Result := False; SQLStr := 'Delete from ' + TableName + ' where ' + FieldIndex + ' = ' + IntToStr(index); if execSQL(sqlStr, errStr) then Result := True; end; //------------------------------------------------------------ function DelTreeFromDB(ParentID: integer): Boolean; var Query: TADOQuery; begin Query := nil; Result := False; try Query := TADOQuery.Create(nil); Query.Connection := Conn; Query.SQL.Text := 'select * from ' + TableName + ' where PID = ' + IntToStr(ParentID); if Query.Active then Query.Close; Query.Open; while Query.Eof = False do begin DelTreeFromDB(Query.FieldValues[FieldIndex]); Result := DelTableFromIndex(Query.FieldByName(FieldIndex).AsInteger); Query.Next; end; finally Query.Free; end; Result := DelTableFromIndex(ParentID); end; //------------------------------------------------------------ begin Result := False; if Node.AbsoluteIndex = 0 then begin raise Exception.Create('禁止删除根节点!'); Exit; end; if DelTreeFromDB(PNodeData(Node.Data)^.Index) then begin TreeView.Items.Delete(Node); Result := True; end; end; //-------------------------------------------------------------- function TTreeUtils.getTreeNodeData(TreeNode: TTreeNode): TNodeData; begin if TreeNode = nil then Result := PNodeData(TreeView.Items.Item[0].Data)^ else Result := PNodeData(TreeNode.Data)^; end; //-------------------------------------------------------------- function TTreeUtils.getSelNodeIndex: integer; var PData: PNodeData; begin Result := -1; if TreeView.Selected = nil then Exit; PData := PNodeData(TreeView.Selected.Data); Result := PData^.Index; end; function TTreeUtils.getSelNodeCaption: string; var PData: PNodeData; begin Result := '; if TreeView.Selected = nil then Exit; PData := PNodeData(TreeView.Selected.Data); Result := PData^.Caption; end; //-------------------------------------------------------------- function TTreeUtils.AddNode(ACaption: string = '新节点'; ANode: TTreeNode = nil): Boolean; var Node, NewNode: TTreeNode; PData: PNodeData; begin Result := True; try if ANode = nil then Node := TreeView.Selected else Node := ANode; New(PData); PData^.Index := getMaxIndex + 1; PData^.Caption := ACaption; sqlStr := 'Insert into ' + TableName + ' (' + FieldIndex + ',' + FieldPID + ',' + FieldCaption + ')' + ' values(' + IntToStr(PData^.Index) + ','; if Node = nil then Node := TreeView.Items.Item[0]; if Node.Level = 0 then sqlStr := sqlStr + '0,"' + ACaption + '")' else sqlStr := sqlStr + IntToStr(PNodeData(Node.Parent.Data)^.Index) + ',"' + ACaption + '")'; if execSQL(sqlStr, errStr) then begin if Node.Level = 0 then NewNode := TreeView.Items.AddChildObject(Node, ACaption, PData) else NewNode := TreeView.Items.AddObject(Node, ACaption, PData); NewNode.ImageIndex := 1; NewNode.SelectedIndex := 2; end; except Result := False; end; end; //-------------------------------------------------------------- function TTreeUtils.AddChildNode(ACaption: string = '新节点'; ANode: TTreeNode = nil): Boolean; var Node, NewNode: TTreeNode; PData: PNodeData; begin Result := True; try if ANode = nil then Node := TreeView.Selected else Node := ANode; New(PData); PData^.Index := getMaxIndex + 1; PData^.Caption := ACaption; sqlStr := 'Insert into ' + TableName + ' (' + FieldIndex + ',' + FieldPID + ',' + FieldCaption + ')' + ' values(' + IntToStr(PData^.Index) + ','; if Node = nil then Node := TreeView.Items.Item[0]; if Node.Level = 0 then sqlStr := sqlStr + '0,"' + ACaption + '")' else sqlStr := sqlStr + IntToStr(PNodeData(Node.Data)^.Index) + ',"' + ACaption + '")'; if execSQL(sqlStr, errStr) then begin NewNode := TreeView.Items.AddChildObject(Node, ACaption, PData); NewNode.ImageIndex := 1; NewNode.SelectedIndex := 2; end;
except Result := False; end; end; //-------------------------------------------------------------- //执行SQL语言 function TTreeUtils.execSQL(sqlStr: string; var errMsg: string): boolean; begin result := false; errMsg := '执行成功!'; try Query.SQL.Text := sqlStr; if Query.Active then Query.Close; Query.ExecSQL; result := true; except on e: Exception do errMsg := e.Message; end; end; //------------------------------------------------------------------------------ function TTreeUtils.getMaxIndex: integer; var i: integer; PNode: PNodeData; begin Result := 0; for i := 0 to TreeView.Items.Count - 1 do begin PNode := PNodeData(TreeView.Items.Item[i].Data); if Result < PNode^.Index then Result := PNode^.Index; end; end; //------------------------------------------------------------------------------ procedure TTreeUtils.FillTree; var H: TTreeFill; begin H := TTreeFill.Create(TreeView, Conn, TableName, RootText, FieldIndex, FieldPID, FieldCaption); end; //------------------------------------------------------------------------------ function TTreeUtils.ModifyNodeCaption(NewCaption: string; Node: TTreeNode): boolean; begin sqlStr := 'Update ' + TableName + ' set ' + FieldCaption + '="' + NewCaption + '" where ' + FieldIndex + ' = ' + IntToStr(PNodeData(Node.Data)^.Index); if execSQL(sqlStr, errStr) then begin Node.Text := NewCaption; PNodeData(Node.Data)^.Caption := NewCaption; end; end; //------------------------------------------------------------------------------ function TTreeUtils.ModifyNodePID(PID: integer; Node: TTreeNode): boolean; function InChildNode(APID: integer; ANode: TTreeNode): boolean; var loop, NStart, NEnd: integer; begin Result := False; NStart := Node.AbsoluteIndex; if Node.getNextSibling = nil then NEnd := TreeView.Items.Count - 1 else NEnd := Node.GetNextSibling.AbsoluteIndex; for loop := NStart + 1 to NEnd - 1 do begin Result := Result or (PNodeData(TreeView.Items.Item[loop].Data)^.Index = PID); end; end; begin Result := False; //如果是根节点则忽略 if Node.AbsoluteIndex = 0 then Exit; //如果PID不变则忽略 if PID = PNodeData(Node.Parent.Data)^.Index then Exit; //如果父节点是自己也则忽略 if PID = PNodeData(Node.Data)^.Index then Exit; //如果父节点编号是它其中一级子节点的编号,则忽略 if InChildNode(PID, Node) then Exit; sqlStr := 'Update ' + TableName + ' set ' + FieldPID + '="' + IntToStr(PID) + '" where ' + FieldIndex + ' = ' + IntToStr(PNodeData(Node.Data)^.Index); if execSQL(sqlStr, errStr) then Result := True; end;
uses Forms, frmMainUnit in 'frmMainUnit.pas' {frmMain}, TreeUtils in 'TreeUtils.pas', TreeFillThrd in 'TreeFillThrd.pas', DMUnit in 'DMUnit.pas' {DM: TDataModule};
{$R *.res}
begin Application.Initialize; Application.CreateForm(TDM, DM); Application.CreateForm(TfrmMain, frmMain); Application.Run; end.