⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 newdbtv.pas

📁 连接数据库treeview控件
💻 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 + -