unit mydbtreeview;
interface
uses
SysUtils, Classes, Controls, ComCtrls,
Menus,Dialogs,DB,ADODB,DesignIntf, DesignEditors,DBCommon ;
type
//字符串属性编辑器1
TStingEditer= class(TStringProperty)
function GetAttributes: TPropertyAttributes; override;
procedure GetValues(Proc: TGetStrProc); override;
end;
//字符串属性编辑器2
TStingmy= class(TStringProperty)
function GetAttributes: TPropertyAttributes; override;
procedure GetValues(Proc: TGetStrProc); override;
end;
Tmydbtreeview = class(TTreeView)
private
FLinkDataSource: TDataSource;
FPopMenu: TPopupMenu;
Fappendnode: TMenuItem;
Fappendchildnode: TMenuItem;
Fdeletenode: TMenuItem;
Fmodifynode: TMenuItem;
Fzknode: TMenuItem;
Fdqnode: TMenuItem;
treels_q: TADOQuery;
FDataactive: boolean;
Fchildtnodevalue: string;
Fparentnodevalue: string;
Fchildtnodeid: string;
Fparentnodeid: string;
Dataname: string;
procedure FSetLinkDataSource(AValue: TDataSource);
procedure FsetDataactive(AValue: boolean);
procedure PDataactive ;
procedure destryMenus ;
procedure destryFPopMenu ;
{ Private declarations }
protected
procedure Notification(AComponent: TComponent;Operation: TOperation);
{ Protected declarations }
public
procedure treeViewsave ; //读取数据库到树
procedure treeViewread ; //读取数据库到树
procedure CreateSubTree(TreeViewls: TTreeView;treepind:integer); //从数据库中读取树
procedure DblClick;override;
procedure DragDrop(Source: TObject; X, Y: Integer); override;
procedure DragOver(Source: TObject; X, Y: Integer; State: TDragState;
var Accept: Boolean); override;
procedure MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer); override;
procedure TreeViewappendnode(Treeviewa:TTreeview); //添加节点
procedure TreeViewappendchildnode(Treeviewa:TTreeview); //添加子节点
procedure TreeViewdeletenode(Treeviewa:TTreeview); //删除节点
procedure treemodify(TreeViewa: TTreeView);//修改节点
procedure treezk(TreeViewa: TTreeView); //展开节点
procedure treedq(TreeViewa: TTreeView);//叠起节点
procedure Onappendnode(Sender: TObject);
procedure Onappendchildnode(Sender: TObject);
procedure Ondeletenode(Sender: TObject);
procedure Onmodifynode(Sender: TObject);
procedure Onzknode(Sender: TObject);
procedure Ondqnode(Sender: TObject);
constructor Create(AOwner:TComponent);override;
destructor Destroy;override;
{ Public declarations }
published
property DataSource: TDataSource read FLinkDataSource write FSetLinkDataSource;
property DataFieldchildvalue: string read Fchildtnodevalue write Fchildtnodevalue;
property DataFieldparentvalue: string read Fparentnodevalue write Fparentnodevalue;
property DataFieldchildid: string read Fchildtnodeid write Fchildtnodeid;
property DataFieldparentid: string read Fparentnodeid write Fparentnodeid;
property Dataactive: boolean read FDataactive write FsetDataactive;
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('mytreeview', [Tmydbtreeview]);
RegisterPropertyEditor(TypeInfo(string), Tmydbtreeview, 'DataFieldchildvalue', TStingEditer);
RegisterPropertyEditor(TypeInfo(string), Tmydbtreeview, 'DataFieldparentvalue', TStingEditer);
RegisterPropertyEditor(TypeInfo(string), Tmydbtreeview, 'DataFieldchildid', TStingEditer);
RegisterPropertyEditor(TypeInfo(string), Tmydbtreeview, 'DataFieldparentid', TStingEditer);
end;
{ Tmytreeview }
constructor Tmydbtreeview.Create(AOwner: TComponent);
begin
inherited;
Fappendnode := TMenuItem.Create(nil);
with Fappendnode do
begin
Caption := '添加节点';
Name := 'appendnode';
OnClick := Onappendnode;
end;
//Fappendnode.ShortCut := ShortCut(Word('E'), [ssCtrl]); //快捷键
Fappendchildnode := TMenuItem.Create(nil);
with Fappendchildnode do
begin
Caption := '添加子节点';
Name := 'appendchildnode';
OnClick := Onappendchildnode;
end;
Fdeletenode := TMenuItem.Create(nil);
with Fdeletenode do
begin
Caption := '删除节点';
Name := 'deletenode';
OnClick := Ondeletenode;
end;
Fmodifynode := TMenuItem.Create(nil);
with Fmodifynode do
begin
Caption := '修改节点';
Name := 'modifynode';
OnClick := Onmodifynode;
end;
Fzknode := TMenuItem.Create(nil);
with Fzknode do
begin
Caption := '展开节点';
Name := 'zknode';
OnClick := Onzknode;
end;
Fdqnode := TMenuItem.Create(nil);
with Fdqnode do
begin
Caption := '叠起节点';
Name := 'dqnode';
OnClick := Ondqnode;
end;
FPopMenu := TPopupMenu.Create(nil);
with FPopMenu do
begin
Name := 'AnPopMenu';
Items.Add(Fappendnode);
Items.Add(Fappendchildnode);
Items.Add(Fdeletenode);
Items.Add(Fmodifynode);
Items.Add(Fzknode);
Items.Add(Fdqnode);
end;
self.PopupMenu := FPopMenu;
end;
procedure Tmydbtreeview.CreateSubTree(TreeViewls: TTreeView;
treepind: integer);
var
sqlstr,str,pstr:string;
ind,pind:integer;
i,j,c:integer;
nod:TTreeNode;
treels_q: TADOQuery;
begin
if Assigned(DataSource) and Assigned(DataSource.DataSet) then
dataname:= GetTableNameFromSQL(TADOQuery (DataSource.DataSet).SQL.Text);
sqlstr:='Select * from '+dataname+' Where '+Fparentnodeid+'='+inttostr(treepind)+' order by '+Fchildtnodeid;
treels_q:=TADOQuery.Create(Self);
treels_q.Connection:=TADOQuery (DataSource.DataSet).Connection ;
treels_q.Active:=false;
treels_q.SQL.Text:=sqlstr;
treels_q.Active:=true;
nod:=TreeViewls.Items.Item[treepind] ;
if treels_q.RecordCount>0
then
while not treels_q.Eof do
begin
str:=treels_q.fieldbyname(Fchildtnodevalue).AsString;
ind:=treels_q.fieldbyname(Fchildtnodeid).AsVariant;
TreeViewls.Items.AddChild(Nod,str);
//递归调用
CreateSubTree(TreeViewls,ind);
treels_q.Next;
end;
FreeAndNil(treels_q);
end;
procedure Tmydbtreeview.DblClick;
begin
inherited;
self.Selected.EditText;
end;
destructor Tmydbtreeview.Destroy;
begin
destryFPopMenu;
FPopMenu.Free;
destryMenus;
inherited;
end;
procedure Tmydbtreeview.destryFPopMenu;
begin
Fappendnode.Free;
Fappendchildnode.Free;
Fdeletenode.Free;
Fmodifynode.Free;
Fzknode.Free;
Fdqnode.Free;
end;
procedure Tmydbtreeview.destryMenus;
var
i:integer;
begin
self.Items.Clear;
end;
procedure Tmydbtreeview.DragDrop(Source: TObject; X, Y: Integer);
var
TempNode : TTreeNode;
AttachMode : TNodeAttachMode;
begin
inherited;
{鼠标释放时执行的语句}
if self.Selected = nil then
Exit;
AttachMode :=naInsert;
{ 注意在这里存在一个bug,当移动结点时,如果目标结点没有子结点,}
{ 则加入的新的子结点会失败,所以先在当前目标结点的下面 }
{ 加入一个临时子结点,移动完毕后,再将临时结点删除 }
self.Items.BeginUpdate;
try
TempNode := self.Items.AddChild( self.DropTarget,
'Temp' );
try
{ 移动选中的结点到目标结点 }
self.Selected.MoveTo(self.DropTarget, AttachMode );
finally
TempNode.Free; { 不要忘了释放临时结点 }
end;
finally
self.Items.EndUpdate;
end;
end;
procedure Tmydbtreeview.DragOver(Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
var
Node : TTreeNode;
begin
inherited;
{鼠标拖动执行语句}
if Source = self then
begin
Node := self.GetNodeAt( X, Y ); {取当前结点}
if Node <> nil then {当前结点不为空才能实现拖拽,accept:=true}
Accept := true;
end;
end;
procedure Tmydbtreeview.FsetDataactive(AValue: boolean);
begin
FDataactive:= AValue;
if (FDataactive=true )
then
PDataactive
else Items.Clear;
end;
procedure Tmydbtreeview.FSetLinkDataSource(AValue: TDataSource);
begin
FLinkDataSource := AValue;
if AValue <> nil then
FLinkDataSource.FreeNotification(self);
{当控件被移除时,用 FreeNotification 方法触发消息,
响应Notification事件。在Notification事件中处理控件被移除的信息!}
end;
procedure Tmydbtreeview.MouseDown(Button: TMouseButton; Shift: TShiftState;
X, Y: Integer);
begin
inherited;
{判断左键按下并且鼠标点在一个结点上开始实现拖拽}
if ( Button = mbLeft ) and
( htOnItem in self.GetHitTestInfoAt( X, Y ) ) then
begin
self.BeginDrag( False );
end;
end;
procedure Tmydbtreeview.Notification(AComponent: TComponent;
Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = DataSource) then
DataSource := nil;
end;
procedure Tmydbtreeview.Onappendchildnode(Sender: TObject);
begin
TreeViewappendchildnode(self);
end;
procedure Tmydbtreeview.Onappendnode(Sender: TObject);
begin
TreeViewappendnode(self);
end;
procedure Tmydbtreeview.Ondeletenode(Sender: TObject);
begin
TreeViewdeletenode(self);
end;
procedure Tmydbtreeview.Ondqnode(Sender: TObject);
begin
treedq(self);
end;
procedure Tmydbtreeview.Onmodifynode(Sender: TObject);
begin
treemodify(self);
end;
procedure Tmydbtreeview.Onzknode(Sender: TObject);
begin
treezk(self);
end;
procedure Tmydbtreeview.PDataactive;
begin
if Assigned(DataSource) and Assigned(DataSource.DataSet) then
begin
treeViewread
end;
end;
procedure Tmydbtreeview.treedq(TreeViewa: TTreeView);
begin
try
TreeViewa.FullCollapse;
TreeViewa.SetFocus;
TreeViewa.Selected.Expand(false);
except
end;
end;
procedure Tmydbtreeview.treemodify(TreeViewa: TTreeView);
begin
try
TreeViewa.Selected.EditText;
except
ShowMessage('请选择要修改的节点');
end;
end;
procedure Tmydbtreeview.TreeViewappendchildnode(Treeviewa: TTreeview);
var
Node : TTreeNode;
i:integer;
begin
try
Node:=Treeviewa.Selected;
i:= Node.AbsoluteIndex;
Treeviewa.Items.AddChild (Treeviewa.Items.Item[i],'新子节点');
except
ShowMessage('请选择要添加的节点');
end;
end;
procedure Tmydbtreeview.TreeViewappendnode(Treeviewa: TTreeview);
var
Node : TTreeNode;
c,i:integer;
begin
try
c:=Treeviewa.Items.Count;
if c<>0
then begin
Node:=Treeviewa.Selected;
i:= Node.AbsoluteIndex;
Treeviewa.Items.Add (Treeviewa.Items.Item[i],'新节点');
end else
Treeviewa.Items.AddFirst( nil, '新节点');
except
ShowMessage('请选择要添加的节点');
end;
end;
procedure Tmydbtreeview.TreeViewdeletenode(Treeviewa: TTreeview);
var
Node : TTreeNode;
begin
try
Node:=Treeviewa.Selected;
Treeviewa.Selected.Delete;
except
ShowMessage('请选择要删除的节点');
end;
end;
procedure Tmydbtreeview.treeViewread;
var
sqlstr,str,pstr:string;
ind,pind:integer;
i,j,c:integer;
nod:TTreeNode;
treels_q: TADOQuery;
TreeViewa: TTreeView;
sqlname: string;
begin
destryMenus;
TreeViewa:=self;
if Assigned(DataSource) and Assigned(DataSource.DataSet) then
dataname:= GetTableNameFromSQL(TADOQuery (DataSource.DataSet).SQL.Text);
sqlname:=Dataname;
treels_q:=TADOQuery.Create(Self);
treels_q.Connection:=TADOQuery (DataSource.DataSet).Connection ;
sqlstr:='Select * from '+ sqlname+' Where '+Fparentnodeid+'=-1 order by '+ Fchildtnodeid ;
treels_q.Active:=false;
treels_q.SQL.Text:=sqlstr;
treels_q.Active:=true;
str:= treels_q.fieldbyname(Fchildtnodevalue).AsString;
FreeAndNil(treels_q);
TreeViewa.Items.AddChild(nil,str);
CreateSubTree(TreeViewa,0);
TreeViewa.FullExpand;
end;
procedure Tmydbtreeview.treeViewsave;
var
str,pstr:string;
ind,pind:integer;
i,j,c:integer;
nod:TTreeNode;
treeviewtable: TADOQuery;
TreeViewa: TTreeView;
sqlname: string;
begin
TreeViewa:=self;
if Assigned(DataSource) and Assigned(DataSource.DataSet) then
dataname:= GetTableNameFromSQL(TADOQuery (DataSource.DataSet).SQL.Text);
sqlname:=Dataname;
treeviewtable:=TADOQuery.Create(Self);
treeviewtable.Connection:=TADOQuery (DataSource.DataSet).Connection ;
treeviewtable.Active:=false;
treeviewtable.SQL.Text:='delete from '+sqlname ;
treeviewtable.ExecSQL;
treeviewtable.Active:=false;
treeviewtable.SQL.Text:='select * from '+sqlname ;
treeviewtable.Active:=true;
c:=TreeViewa.Items.Count;
for i:=0 to c-1 do
begin
nod:=TreeViewa.Items.Item[i];
str:=nod.Text;
if i<>0 then
begin
pstr:=nod.Parent.Text;
pind:=nod.Parent.AbsoluteIndex;
end
else begin
pstr:='nil' ;
pind:=-1;
end;
ind:=i;
treeviewtable.Append;
treeviewtable.FieldByName(Fparentnodevalue).AsVariant:=pstr;
treeviewtable.FieldByName(Fchildtnodevalue).AsVariant:=str;
treeviewtable.FieldByName(Fchildtnodeid).AsVariant:=ind;
treeviewtable.FieldByName(Fparentnodeid).AsVariant:=pind;
treeviewtable.Post;
end;
end;
procedure Tmydbtreeview.treezk(TreeViewa: TTreeView);
begin
try
TreeViewa.FullExpand;
except
end;
end;
{ TStingEditer }
function TStingEditer.GetAttributes: TPropertyAttributes;
begin
Result := [paValueList, paSortList, paRevertable];
end;
procedure TStingEditer.GetValues(Proc: TGetStrProc);
var
i,c:integer;
mDataSource: Tmydbtreeview;
begin
inherited;
mDataSource:=GetComponent(0) as Tmydbtreeview ;
c:= mDataSource.DataSource.DataSet.FieldCount;
for i:=0 to c-1 do
Proc( mDataSource.DataSource.DataSet.Fields[i].FieldName);
end;
{ TStingmy }
function TStingmy.GetAttributes: TPropertyAttributes;
begin
Result := [paValueList, paSortList, paRevertable];
end;
procedure TStingmy.GetValues(Proc: TGetStrProc);
begin
inherited;
Proc('我们');
Proc('我们');
Proc('你们');
end;
end.