delphi中VirtualStringTree樹使用方法

 

例子:建立了一個樹名爲VirtualStringTree1,第一列顯示數據庫字段ID的值,標題爲編號;第二列顯示字段Name的值,標題爲名字。
1、【TVirtualStringTree經常使用屬性】
    BorderStyle   :設置邊框選項  bsSingle設置單邊框
   爲TVirtualStringTree添加列及列標題:   
    Header--Columns : 設置列  點擊「…」,在彈出界面點擊add new按鈕,就增長一列,在其text中輸入列名,在width輸入列寬度;
    Header--options-hovisible: 設置列可顯示!! node

    Header-Style  :設置樹的主題類型
    ScrollBaroptions--AlwaysVisible 滾動條是否老是可見
    ScrollBarOptions-ScrollBars-ssVertical  設置爲只有豎向滾動條
   爲TVirtualStringTree添加勾選框、選擇框、複選框:
     TreeOptions----MiscOpitions---toCheckSupport  設置爲True便可
     CheckImageKind  爲勾選框設置圖標sql

     Header-Maincolumn  設置勾選框在第幾列前面,默認爲0也就是在第一列前面數據庫

      並設置ongettext()事件和onInitailNode()事件,見下面事件部分。函數

--------------------------------------------------------------------------------------------------------------------------------------------字體

2、 【TVirtualStringTree經常使用方法 】 
    VirtualStringTree1.NodeDataSize := sizeOf(TMyNodeData);  //設置佔存儲空間大小指針

   樹節點選中:VirtualStringTree1.Selected[p_node]True;  //設置節點p_node處於選中狀態orm

   樹節點勾選框選中:p_node.CheckState:=cscheckedNormal;//設置節點p_node處於勾選狀態事件

   onchecked()事件:設置節點勾選時觸發的事件,其中第二個參數就是勾選的節點ci

   取消選中的節點:VirtualStringTree1.ClearSelection;get

    樹節點刪除:  VirtualStringTree1.DeleteSelectedNodes; //刪除選中的節點

    樹節點內容清空:VirtualStringTree1.clear;

    獲得樹的第一個節點:VirtualStringTree1.GetFirst;

    獲得樹的第一個選中節點:VirtualStringTree1.GetFirstSelected;

     獲得節點的下一個節點:VirtualStringTree1.Getnext(p_node);

    獲得下一個選中的節點:VirtualStringTree1.GetNextSelected(p_node);

    獲得父節點:p_node.Parent

    獲得子節點個數:p_node.ChildCount

    獲得第一個子節點:p_node.FirstChild

    獲得最後一個子節點:p_node.FirstChild

    獲得上一個兄弟節點:p_node.PrevSibling

    獲得下一個兄弟節點:p_node.NextSibling

---------------------------------------------------------------------------------------------------------------------------

3、【TVirtualStringTree顯示數據庫字段內容】:

//定義一個指針

type

  Tjdtransline =record

       id: integer;     //編號

      name : string;  //名稱

       levelID : integer;//級別,例如總公司levelID 爲0、二級公司爲一、三級公司levelID 爲2等

      FatherID:integer;  //節點的父節點ID

  end;

  pjdtransline =^Tjdtransline ;

private

   procedure iniVirtualStringTree1;   //事件聲明爲全局私有事件

 

//樹顯示數據庫字段內容

procedure form1.iniVirtualStringTree1;

var

p_jdtransline: pjdtransline;

begin

  while not adoquery1.Eof do
  begin
    New(p_jdtransline);
    p_jdtransline^.ID := client_dataset_jdtransline.FieldByName('ID').AsInteger;
    p_jdtransline^.Name := Trim(client_dataset_jdtransline.FieldByName('Name').AsString);
    VirtualStringTree1.AddChild(nil, p_jdtransline);  //*********************添加樹節點***********************************
    adoquery1.Next;
  end;

end;

 

//在窗體建立時調用樹的初始化事件

procedure form1.formcreate(sender:Tobject);

begin

  iniVirtualStringTree1;

end;

//設置各列字段的顯示OnGetText() var
  p_node_data       : PMyNodeData;
  p_jdtransline     : PJDTranslineTree;
begin
  p_node_data := VirtualStringTree1.GetNodeData(Node);
  p_jdtransline := p_node_data^.my_data_ptr;

    case Column of
       0 : CellText :=  inttostr( p_jdtransline^.ID);

        1: CellText := p_jdtransline^.Name;

      end;

end;

------------------------------------------------------------------------------------------------------------------------------------

4、 【TVirtualStringTree設置節點展開與摺疊的圖標 】 
  OnInitNode()  //設置結點的節點是否有子節點類型(‘+’、‘—’顯示)

  begin
  Include(InitialStates, ivsHasChildren);
  Node.CheckType := ctTriStateCheckBox;

  end;

-------------------------------------------------VirtualStringTree樹拖動操做實現開始-------------------------------------------------------------------------

5、【VirtualStringTree樹節點拖動實現】

主要設置其DragOver和DragDrop事件。其中DragOver控制是否容許移動;DragDrop控制移動後執行的操做。

//1、DragOver事件
procedure form1.VirtualStringTree1Over(
  Sender: TBaseVirtualTree; Source: TObject; Shift: TShiftState;
  State: TDragState; Pt: TPoint; Mode: TDropMode; var Effect: Integer;
  var Accept: Boolean);

 

 //事件內部函數1.獲取節點的值

  function GetVNodeData(vn: PVirtualNode; vst: TVirtualStringTree): PVNodeData;
  begin
    Result := PVNodeData(PPointer(vst.GetNodeData(vn))^);
  end;

 

 //事件內部函數2.獲取全部選中節點的列表
  function GetSelectedVNodes(vst: TVirtualStringTree): TVNodeArray;
  var
    list: TList;
    n: PVirtualNode;
    i: Integer;
  begin
    list := TList.Create;
    n := vst.GetFirstSelected;
    while n <> nil do
    begin
      list.Add(n);
      n := vst.GetNextSelected(n);
    end;

    SetLength(Result, list.Count);
    for i := 0 to list.Count-1 do
    begin
      Result[i] := list[i];
    end;

    list.Free;
  end;

 

// //事件內部函數3.判斷是不是移動到本身的父節點

  function IsSameLevel(selectedList: TVNodeArray): Boolean;
  var
    n: PVirtualNode;
    l: Cardinal;
    i: Integer;
  begin
    Result := False;
    if Length(selectedList) = 0 then
    begin
     Result := True;
     Exit;
    end;
    for i := 0 to High(selectedList) do
    begin
      n := selectedList[i];
      if  n.Parent = Sender.DropTargetNode then //移動到本身父節點不容許移動
      begin    
        HintBar.Panels[0].Text := '不容許移動到本身的父節點';
        Result := True;
        Break;
      end;

    end;
  end;

 

  // //事件內部函數4.判斷目標(父、子)節點中是否與選中節點名稱相同
  function IsExistSelectObject(selectedList: TVNodeArray): Boolean;
  var
    dstNode             : PVirtualNode;
    n                   : PVirtualNode;
    i                   : Integer;
    TargetChildNode     : PVirtualNode;
    TargetParentNode    : PVirtualNode;
    SelectNodeName      : String;
    TargetNodeName      : String;
    TargetChildNodeName : String;
    TargetParentNodeName: String;
    SelectNodeLevel     : Integer;
    TargetNodeLevel     : Integer;
  begin
    Result := False;
    if Length(selectedList) = 0 then
    begin
     Exit;
    end;
    dstNode          := Sender.DropTargetNode;
    TargetChildNode  := dstNode.FirstChild;
    TargetParentNode := dstNode.Parent;   
    TargetNodeName   := pjdtransline(VtPurview.GetNodeData(dstNode)^).name;
    TargetNodeLevel  := pjdtransline(VtPurview.GetNodeData(dstNode)^).LevelID;

    for i := 0 to High(selectedList) do
    begin
      n := selectedList[i];
      SelectNodeName   := pjdtransline(VtPurview.GetNodeData(n)^).name;
      SelectNodeLevel  := pjdtransline(VtPurview.GetNodeData(n)^).LevelID;

      if (TargetNodeLevel > SelectNodeLevel) then  //目標節點級別不能比選中節點級別低
      begin
        HintBar.Panels[0].Text := '目標節點級別比選中節點級別低,不能移動!';
        Result := True;
        Break;
      end;

      if (TargetNodeName = SelectNodeName) then  //目標節點與選中節點相同
      begin
        HintBar.Panels[0].Text := '目標節點值與選中節點值相同,不能移動!';
        Result := True;
        Break;
      end;

      while  TargetChildNode <> nil do
      begin
       TargetChildNodeName := pjdtransline(VtPurview.GetNodeData(TargetChildNode)^).name;
        if TargetChildNodeName = SelectNodeName then  //目標子節點與選中節點相同
        begin
          HintBar.Panels[0].Text := '目標子節點存在與選中節點值相同的節點,不能移動!';
          Result := True;
          Break;
        end;
        TargetChildNode := TargetChildNode.NextSibling;
      end;
    end;
  end;

 

  // //事件內部函數6.判斷是否移動本身子節點或子子節點
  function IsAncestor(vnDescendant, vnAncestor: PVirtualNode): Boolean;
  var
    p: PVirtualNode;
  begin
    Result := False;
    p := vnDescendant.Parent;
    while p <> nil do
    begin
      if p = vnAncestor then
      begin
        HintBar.Panels[0].Text := '不能移動到本身的子節點或子子節點';
        Result := True;
        Exit;
      end;
      p := p.Parent;
    end;
  end;

 

  //事件定義變量
var                                            

  Node : TTreeNode;
  VirtualStringTree1: TVirtualStringTree;
  dstNode, srcNode: PVirtualNode;
  srcText, dstText, s: string;
  selectedList: TVNodeArray;
  i: Integer;
begin    
  Accept := False;
  if not (Source is TVirtualStringTree) then Exit;

  VirtualStringTree1 := TVirtualStringTree(Source);
  dstNode := Sender.DropTargetNode;
  srcNode := VirtualStringTree1.FocusedNode;
  if (srcNode = nil) or (dstNode = nil) then Exit;
  if srcNode = dstNode then
  begin    
    HintBar.Panels[0].Text := '目標節點必須與選中節點不一樣!';
    Exit;
  end;
  selectedList := GetSelectedVNodes(VirtualStringTree1);
  if IsSameLevel(selectedList) then
  begin
    Accept := False;
    Exit;
  end;

  if IsExistSelectObject(selectedList) then
  begin
    Accept := False;
    Exit;
  end;

//  dstText := GetVNodeData(dstNode, VirtualStringTree1).Name;
  case Mode of
    dmAbove:  // 成爲父節點;
      begin
        Accept := False;
      end;
    dmBelow:  // 成爲子節點,本例主要採用成爲子節點模式
      begin
        for i := 0 to High(selectedList) do
        begin
          srcNode := selectedList[i];
          Accept := not IsAncestor(dstNode, srcNode);
          if not Accept then Break;
        end;
      end;
    dmOnNode: // 成爲同級節點
      begin
        for i := 0 to High(selectedList) do
        begin
          srcNode := selectedList[i];
          Accept := not IsAncestor(dstNode, srcNode);
          if  Accept then
            HintBar.Panels[0].Text := '能夠移動'
          else
            Break;
        end;

      end;
    dmNowhere:
      Accept := False;
  else
  end;
end;

 

2、DragDrop事件


procedure Tform1.VirtualStringTree1DragDrop(
  Sender: TBaseVirtualTree; Source: TObject; DataObject: IDataObject;
  Formats: TFormatArray; Shift: TShiftState; Pt: TPoint;
  var Effect: Integer; Mode: TDropMode);
//事件內部函數--獲取選中節點的list
  function GetSelectedVNodes(VtPurview: TVirtualStringTree): TVNodeArray;
  var
    list: TList;
    n: PVirtualNode;
    i: Integer;
  begin
    list := TList.Create;
    n := VtPurview.GetFirstSelected;
    while n <> nil do
    begin
      list.Add(n);
      n := VtPurview.GetNextSelected(n);
    end;

    SetLength(Result, list.Count);
    for i := 0 to list.Count-1 do
    begin
      Result[i] := list[i];
    end;

    list.Free;
  end;
var
  VirtualStringTree1: TVirtualStringTree;
  dstNode, srcNode: PVirtualNode;
  selectedList: TVNodeArray;
  i: Integer;
  TargetNodeID : integer;
  SelectNodeID : integer;
  SelectNodeFID: integer; 
  sql_str      : string;
begin
  VirtualStringTree1 := TVirtualStringTree(Source);
  dstNode := Sender.DropTargetNode;
  TargetNodeID := PPurview(VtPurview.GetNodeData(dstNode)^).ID;
  selectedList := GetSelectedVNodes(VirtualStringTree1);
  srcNode := VirtualStringTree1.FocusedNode;
  if (srcNode = nil) or (dstNode = nil) then Exit;

  case Mode of
    dmAbove:  // 成爲父節點;
      begin
      end;
    dmBelow:  // 成爲子節點
      begin   
       if IDYES = MessageBox(Handle, PChar('是否將操做保存到數據庫?'), '確認保存',MB_ICONQUESTION or MB_YESNO or MB_DEFBUTTON2) then
       begin
        for i := 0 to High(selectedList) do
        begin
          srcNode := selectedList[i];
          VirtualStringTree1.MoveTo(srcNode, dstNode, amAddChildFirst, False);

          SelectNodeID := PPurview(VtPurview.GetNodeData(srcNode)^).ID;
          SelectNodeFID := PPurview(VtPurview.GetNodeData(srcNode)^).FatherID;
          //執行數據庫操做    
           if  sql_str = '' then
            sql_str := Format('exec p_VehicleGroupTreeDragMove %d,%d,%d ',
                               [SelectNodeID,
                                SelectNodeFID,
                                TargetNodeID
                               ])
           else
            sql_str := sql_str + Format(';exec p_VehicleGroupTreeDragMove %d,%d,%d ',
                               [SelectNodeID,
                                SelectNodeFID,
                                TargetNodeID
                               ]);
        end;
        VirtualStringTree1.Sort(dstNode, 0, sdAscending, False);
       end
       else
        exit;
      end;
    dmOnNode: // 成爲同級節點
      begin
      end;
    dmNowhere:  
      begin
      end;
    else
  end;

  if sql_str<>'' then
  begin
    ExcuteSQL(sql_str);  //保存拖動後節點的上下級關係
  end;
end;

-------------------------------------------------VirtualStringTree樹拖動操做實現結束-------------------------------------------------------------------------

6、實現VirtualStringTree(TVirtualStringTree)樹節點字體顏色分多顏色顯示 oncellpaint()事件

 客戶要求盲區或掉線的字體要顯示紅色,速度值要顯示灰色

 

代碼以下:

procedure TfrmMain.vtActiveVehiclePaintText(Sender: TBaseVirtualTree;
  const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
  TextType: TVSTTextType);

begin

  p_node_data := TGPSClientVTVUtils.ExtractActiveVehicleNodeData(vtActiveVehicle, Node);  //獲取節點data
  if not Assigned(p_node_data) then
    Exit;
  vInfo    := PGPSClientVehicleInfoColumn(vtActiveVehicle.Header.Columns[Column].Data);  
  if vInfo <> nil then
  begin
   if (Pos('盲區',p_node_data^.CarInfo.GpsInfo.GpsState)>0) and   //判斷節點值知足某條件
         (vInfo^.FieldInfo.FieldName = 'GPS_Speed') then                //判斷是哪一個列,若是是整個節點都變顏色可不需此條件
      TargetCanvas.Font.Color := clMedGray;                               //速度列變灰色
   if (Pos('盲區',p_node_data^.CarInfo.GpsInfo.GpsState)>0) and
         (vInfo^.FieldInfo.FieldName = 'GPS_Precision') then
      TargetCanvas.Font.Color := clred;                                    //精度列變紅色

   if (SecondsBetween(Now(), p_node_data^.CarInfo.GpsInfo.GPSTime)>=7200) and      //盲區條件    

        (vInfo^.FieldInfo.FieldName = 'GPS_Speed') then            //速度列

          TargetCanvas.Font.Color := clMedGray;       if (SecondsBetween(Now(), p_node_data^.CarInfo.GpsInfo.GPSTime)>=7200) and         (vInfo^.FieldInfo.FieldName = 'GPS_RealStatus') then      TargetCanvas.Font.Color := clred;  end;

相關文章
相關標籤/搜索