?? newdbtv.pas
字號:
//該構件的功能是建立從數據庫內建立三級樹,子葉可以從另外的數據庫中顯示詳細項
//要求主數據庫的索引字段為6byte,ABC結構
unit newdBTV;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls,dbtables,db;
type
TNewDBTV = class(TTreeView)
private
{ Private declarations }
FtvStr: TStringList;
Fselectstr:TStringList;
Fchangeimage:boolean;
FActive: boolean;//激活
FDisplayRootNode: boolean;//根節點
FBytes: Tstrings;//每層占用關鍵字串的字節數
FMastDataSource: TDataSource; //SQL
FDetailDataSource: TDataSource; //SQL
FFilterString:string;
procedure ActiveTree(InVal: boolean);
procedure setByte(Value: TStrings);
function CreateTree:boolean; //建立樹
procedure SetMastDataSource(Value: TDataSource);
procedure SetDetailDataSource(Value: TDataSource);
protected
procedure Click;override;
public
constructor Create(AOwner: TComponent);override;
destructor Destroy;override;
procedure editNode(DispStr,KeyStr:string);//修改當前節點
procedure delNode;//刪除當前節點
function GetNodeKeyStr(tn:TTreeNode):string;//得到當前節點的鍵值
function AddNode(tn:TTreeNode;DispStr,KeyStr:string):TTreeNode;//加子節點
procedure ClearTree;//清除樹
published
property Active:boolean read FActive
write ActiveTree;
property Bytes:Tstrings read FBytes
write SetByte;
property MastDataSource:TDataSource read FMastDataSource
write SetMastDataSource;
//sql語句中,規定第0個field為鍵值,第1個field為顯示字段,
//第2個field為鍵值長度
property DetailDataSource:TDataSource read FDetailDataSource
write setDetailDataSource;
//sql語句中,規定第0個field為鍵值,第1個field為顯示字段,
//第2個field為連接字段
property changeimage:boolean read Fchangeimage write Fchangeimage;
property DisplayRootNode:boolean read FDisplayRootNode write FDisplayRootNode;
property FilterString:string read FFilterString write FFilterString;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('samples', [TNewDBTv]);
end;
constructor TNewdbTV.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
Fchangeimage:=false;
readonly:=true;
self.HideSelection:=false;
FActive:=false;
FtvStr:=TStringList.create;
Fselectstr:=TStringList.create;
FBytes:=TStringList.create;
FDisplayRootNode:=false;
FFilterString:='';
end;
destructor TNewdbTV.Destroy;
begin
FtvStr.free;
Fselectstr.free;
FBytes.Free;
FMastDataSource:=nil;
FDetailDataSource:=nil;
inherited Destroy;
end;
function TNewdbTV.GetNodeKeyStr(tn:TTreeNode):string;//得到節點的鍵值
begin
if tn.AbsoluteIndex<>-1 then result:=FtvStr[tn.AbsoluteIndex]
else result:='';
end;
function TNewdbTV.AddNode(tn:TTreeNode;DispStr,KeyStr:string):TTreeNode;//加節點
begin
if tn=nil then
Result:=Items.Add(tn,DispStr)
else
Result:=Items.AddChild(tn,DispStr);
FtvStr.insert(result.AbsoluteIndex,KeyStr);//影射樹
if Fbytes.Count=0 then
begin
if FDetailDataSource=nil then
Fselectstr.insert(result.AbsoluteIndex,'1')//無子節點
else
Fselectstr.insert(result.AbsoluteIndex,'0');
end
else
Fselectstr.insert(result.AbsoluteIndex,'0');//可能有子節點
Result.ImageIndex:=Result.Level+1; //boot
if Fchangeimage then Result.selectedIndex:=Result.ImageIndex;
end;
procedure TNewdbTv.editNode(DispStr,KeyStr:string);//修改當前節點
var i:integer;
s1,s2:string;
begin
if selected=nil then exit;
selected.Text:=DispStr;
s1:=FtvStr.strings[selected.AbsoluteIndex];
FtvStr.strings[selected.AbsoluteIndex]:=keystr;
if FBytes.Count=0 then exit;
if FDetailDataSource<>nil then exit;
//修改其子節點得代碼
for i:=selected.AbsoluteIndex+1 to FtvStr.Count-1 do
begin
s2:=FtvStr.strings[i];
if s1=copy(s2,1,length(s1)) then
FtvStr.strings[i]:=keystr+copy(s2,length(s1)+1,length(s2))
else
break;
end;
end;
procedure TNewdbTv.delNode;//刪除當前節點
var s,s1:string;
i:integer;
begin
if selected=nil then exit;
i:=selected.AbsoluteIndex;
s:=FtvStr.strings[selected.AbsoluteIndex];
selected.Delete;
if (FBytes.Count=0)or(FdetailDatasource<>nil) then
begin
FtvStr.delete(i);
FselectStr.delete(i);
exit;
end;
//刪除其子節點得代碼
while true do
begin
FtvStr.delete(i);
FselectStr.delete(i);
if i=FtvStr.count then break;
s1:=copy(FtvStr.strings[i],1,length(s));
if s1<>s then break;
if FtvStr.strings[i]='' then break;
end;
end;
procedure TNewdbTV.ClearTree;//清除樹
begin
items.Clear;
FselectStr.clear;
FtvStr.Clear;
end;
procedure TNewDBTv.ActiveTree(InVal: boolean);
begin
FActive:=Inval;
ClearTree;
if Inval then
begin //建立樹
if FMastDatasource=nil then
begin
FActive:=false;
exit;
end;
if not CreateTree then
begin //建立樹
ClearTree;
FActive:=false;
exit;
end;
end;
end;
procedure TNewDBTv.setmastDatasource(Value: TDatasource);
begin
if FmastDatasource<>Value then
begin
FmastDatasource:=Value;
ClearTree;
FActive:=false;
end;
end;
procedure TNewDBTv.setdetailDatasource(Value: TDatasource);
begin
if FDetailDatasource<>Value then
begin
FDetailDatasource:=Value;
ClearTree;
FActive:=false;
end;
end;
procedure TNewDBTv.setByte(Value: TStrings);
begin //設置樹的分層方法,即每層所占關鍵串的字節數,隱含為2
ClearTree;//清除樹
FActive:=false;
if FBytes.Text <> Value.Text then
begin
FBytes.BeginUpdate;
try
FBytes.Assign(value);
finally
FBytes.EndUpdate;
end;
end;
end;
function TNewDBTv.CreateTree:boolean; //建立樹
var root,node:ttreenode;
begin
result:=false;
if FMastDatasource.dataset=nil then
begin
messagebox(application.handle,pchar('主表數據集不存在!'),'警告',0);
exit;
end;
if FMastDatasource.dataset.active=false then
try
FMastDatasource.dataset.Open;
except
on e:exception do
begin
messagebox(application.handle,pchar('主表打開失敗!'+e.message),'警告',0);
exit;
end;
end;
FmastDatasource.dataset.first;
if Fmastdatasource.dataset.FieldCount<3 then
begin
messagebox(application.handle,'主表字段數不能小于3!','警告',0);
exit;
end;
if FdetailDatasource<>nil then
begin
if FdetailDatasource.dataset=nil then
begin
messagebox(application.handle,pchar('子表數據集不存在!'),'警告',0);
exit;
end;
if FDetailDataSource.dataset.active=false then
try
FdetailDataSource.dataset.Open;
except
on e:exception do
begin
messagebox(application.handle,pchar('子表打開失敗!'+e.message),'警告',0);
exit;
end;
end;
if FDetailDatasource.dataset.FieldCount<3 then
begin
messagebox(application.handle,'子表字段數不能小于3!','警告',0);
exit;
end;
FDetailDatasource.dataset.first;
end;
if FDisplayRootNode then
begin
root:=AddNode(nil,'','');
node:=root;
end
else
node:=nil;
if FmastDatasource.dataset.isempty then
begin
result:=true;
exit;
end;
FmastDatasource.dataset.filter:=FmastDatasource.dataset.fields[2].fieldname+'='+trim(FmastDatasource.dataset.fields[2].asstring);
if FFilterString<>'' then
FmastDatasource.dataset.filter:=FmastDatasource.dataset.filter+' and '+FFilterString;
if Fbytes.Count<>0 then FmastDatasource.dataset.filtered:=true;//第1層節點
items.BeginUpdate;
root:=AddNode(node,trim(FmastDatasource.dataset.fields[1].asString),trim(FmastDatasource.dataset.fields[0].asString));
FmastDatasource.dataset.Next;
while not(FmastDatasource.dataset.eof) do
begin
AddNode(node,trim(FmastDatasource.dataset.fields[1].asString),trim(FmastDatasource.dataset.fields[0].asString));
FmastDatasource.dataset.Next;
end;
selected:=root;
click;
if not root.Expanded then root.Expand(false);
items.EndUpdate;
Result:=true;
FmastDatasource.dataset.filtered:=false;
end;
//加當前節點得下級節點
procedure TNewdbtv.Click;
var node:ttreenode;
i:integer;
s:string;
label lb;
begin
inherited;
if FActive=false then exit;
if selected=nil then exit;
if fselectstr[selected.AbsoluteIndex]='1' then exit;
if selected.HasChildren then exit;
fselectstr[selected.AbsoluteIndex]:='1';
if (Fdetaildatasource<>nil)and(ftvstr[selected.AbsoluteIndex]<>'') then
if length(ftvstr[selected.AbsoluteIndex])=length(trim(FdetailDatasource.dataset.Fields[2].AsString)) then
begin
FdetailDatasource.dataset.filtered:=false;
FdetailDatasource.dataset.Filter:=FdetailDatasource.dataset.fields[2].fieldname+'='''+ftvstr[selected.AbsoluteIndex]+'''';
FdetailDatasource.dataset.Filtered:=true;
while not FdetailDatasource.dataset.eof do
begin
node:=AddNode(selected,trim(FdetailDatasource.dataset.fields[1].asString),trim(FdetailDatasource.dataset.fields[0].asString));
fselectstr[node.AbsoluteIndex]:='1';
FdetailDatasource.dataset.Next;
end;
FdetailDatasource.dataset.filtered:=false;
end;
if Fbytes.Count-1<= self.Selected.Level then exit;
FmastDatasource.dataset.filtered:=false;
FmastDatasource.dataset.filter:=
FmastDatasource.dataset.fields[2].fieldname+'='+inttostr(length(ftvstr[selected.AbsoluteIndex])+strtoint(Fbytes[self.Selected.Level+1]));
if FFilterString<>'' then
FmastDatasource.dataset.filter:=FmastDatasource.dataset.filter+' and '+FFilterString;
i:=length(ftvstr[selected.AbsoluteIndex]);
s:=ftvstr[selected.AbsoluteIndex];
FmastDatasource.dataset.filtered:=true;
while not FmastDatasource.dataset.eof do
begin
if copy(FmastDatasource.dataset.fields[0].asString,1,i)=s then
AddNode(selected,trim(FmastDatasource.dataset.fields[1].asString),trim(FmastDatasource.dataset.fields[0].asString));
FmastDatasource.dataset.Next;
end;
FmastDatasource.dataset.filtered:=false;
end;
end.
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -