https://www.cnblogs.com/FKdelphi/p/5843135.html

也可参考 ExpressDBTreeView学习(06)  uniGUI前添加checkBox

 

在Delphi10.3运行成功Win7-32位,示例代码下载。只适合Windows平台

1.引用单元

2.定义私有过程

3.过程体代码

4.点击连选处理

5.生成节点

6.查看是否选中

7.取消所有选中/全选

8只选择叶结点

8.1从根一直到叶的 路径

9把多层次的 XML 文档解析为 TreeView 显示


//1.引用单元
uses Commctrl ;
//2.定义私有过程
  procedure tvToggleCheckbox(TreeView: TTreeView;Node: TTreeNode;isclick:boolean =false);
  procedure SetChecked(Node: TTreeNode; Checked: Boolean);
  function IsChecked(Node: TTreeNode): Boolean;
//3.过程体代码
//检查某个节点是否被 选中
function TForm1.IsChecked(Node: TTreeNode): Boolean;
var
  TvItem :TTVItem;
begin
  TvItem.Mask := TVIF_STATE;
  TvItem.hItem := Node.ItemId;
  TreeView_GetItem(Node.TreeView.Handle, TvItem);
  Result := (TvItem.State and TVIS_CHECKED) = TVIS_CHECKED;
end;
//让 某个节点被 选中
procedure TForm1.SetChecked(Node: TTreeNode; Checked: Boolean);
var
TvItem :TTVItem;
begin
  FillChar(TvItem, SizeOf(TvItem), 0);
  with TvItem do
  begin
    hItem := Node.ItemId;
    Mask := TVIF_STATE;
    StateMask := TVIS_STATEIMAGEMASK;
    if Checked then
      TvItem.State :=TVIS_CHECKED
    else
      TvItem.State :=TVIS_CHECKED shr 1;
    TreeView_SetItem(Node.TreeView.Handle, TvItem);
  end;
end;
// 对节点中所有 子节点 都 选中或 未选中 状态
procedure TForm1.tvToggleCheckbox(TreeView: TTreeView;
Node: TTreeNode ;isclick :boolean=false);
var CurNode, ParentNode, GrandSonNode,sonNode: TTreeNode;
flg1: boolean;
begin
  CurNode :=node;
  with TreeView do
  begin
    if IsChecked(CurNode) then //
    begin
      sonNode := CurNode.GetFirstChild; //遍历子树,选中 则子节点 全部 为选中;
      while sonNode<>nil do
      begin
        SetChecked(sonNode, true);
        tvToggleCheckbox(TreeView,sonNode,true);
        sonNode := sonNode.GetNextSibling;
      end;
      ParentNode:= CurNode.Parent; //父;
      if ParentNode<>nil then
      begin
        if not isChecked(parentNode) then
        begin
          GrandSonNode := ParentNode.GetFirstChild; //遍历子树;
          flg1 := false;
          while GrandSonNode<>nil do
          begin
            if (not IsChecked(GrandSonNode)) then //true,有未选中
            flg1 := true;
            if flg1 then //已有、退出loop;
            GrandSonNode := nil
            else
            GrandSonNode := GrandSonNode.GetNextSibling;
          end;
          SetChecked(ParentNode, not flg1);
          tvToggleCheckbox(TreeView,ParentNode,false);
        end;
      end; // end parentNode 不等于空
    end
    else if not IsChecked(CurNode) then
    begin
      ParentNode := CurNode.Parent; //父;
      if ParentNode<>nil then
      begin
        if isChecked(parentNode) then
        begin
          SetChecked(ParentNode, false);
          tvToggleCheckbox(TreeView,ParentNode);
        end;
      end; //end parentnode
      if (isclick) then
      begin
        sonNode := CurNode.GetFirstChild; //遍历子树,未选中 则子节点 全部 为未选中;
        while sonNode<>nil do
        begin
          SetChecked(sonNode, false);
          tvToggleCheckbox(TreeView,sonNode,true);
          sonNode := sonNode.GetNextSibling;
        end;
      end;
    end;
  end;
end;
//4.点击连选处理
procedure TForm1.TreeView1Click(Sender: TObject);
var
  P:TPoint;
  treenode :TTreeNode;
begin
  GetCursorPos(P);
  P := TreeView1.ScreenToClient(P);
  if (htOnStateIcon in TreeView1.GetHitTestInfoAt(P.X,P.Y)) then
  begin
    treenode := TreeView1.GetNodeAt(P.X,P.Y);
    tvToggleCheckbox(TreeView1,treenode ,true);
  end;
end;
//5.生成节点
procedure TForm1.FormCreate(Sender: TObject);
begin
  //仅仅这一句话就能让treeview 显示复选框
  SetWindowLong(TreeView1.Handle, GWL_STYLE, GetWindowLong(TreeView1.Handle, GWL_STYLE) or $00000100);
//  SetWindowLong(H, GWL_STYLE, GetWindowLong(H, GWL_STYLE) or TVS_CHECKBOXES);  //这名同上一个意思
  {下面的代码只是给 TreeView 添加内容}
  with TreeView1 do
  begin
     Align := alLeft;
     Items.Add(nil, 'AAA');
     Items.Add(nil, 'BBB');
     Items.Add(nil, 'CCC');
     Items.AddChild(Items[2], '111');
     Items.AddChild(Items[2], '222');
     Items.AddChild(Items[2], '333');
  end;
end;
//6.查看是否选中
procedure TForm1.Button1Click(Sender: TObject);
var
  Node: TTreeNode;
  TVI: TTVItem;
begin
  for Node in TreeView1.Items do
  begin
    TVI.mask := TVIF_STATE;
    TVI.hItem := Node.ItemId;
    TreeView_GetItem(TreeView1.Handle, TVI);
    if TVI.state and $2000 = $2000 then
      ShowMessage(Node.Text);
  end;
end
//7.取消所有选中、全选
procedure TForm1.Button2Click(Sender: TObject);
var
  Node: TTreeNode;
  TVI: TTVItem;
begin
  for Node in TreeView1.Items do
  begin
    TVI.mask := TVIF_STATE;
    TVI.hItem := Node.ItemId;
    TVI.stateMask := TVIS_STATEIMAGEMASK;
    TVI.state := $2000 shr 1;// TVI.state := $2000 ;//为全选
    TreeView_SetItem(TreeView1.Handle, TVI);
  end;
end
procedure TForm9.Button1Click(Sender: TObject);
var    //8只选择叶结点
  Node: TTreeNode;
  TVI: TTVItem;
begin
  for Node in TreeView1.Items do
  begin
    TVI.mask := TVIF_STATE;
    TVI.hItem := Node.ItemId;
    TreeView_GetItem(TreeView1.Handle, TVI);
    if (TVI.state and $2000 = $2000) and (not Node.HasChildren) then
    LISTBOX1.Items.Add(Node.Text);

  end;

end;

 8.1从根一直到叶的 路径

procedure TForm9.Button1Click(Sender: TObject);
var
  Node: TTreeNode;
  TVI: TTVItem;

  aStr:string;
  tempNode: TTreeNode;
begin
  for Node in TreeView1.Items do
  begin
    TVI.mask := TVIF_STATE;
    TVI.hItem := Node.ItemId;
    TreeView_GetItem(TreeView1.Handle, TVI);
    if TVI.state and $2000 = $2000 then  begin

      aStr:=node.Text;
      tempNode  :=Node;
     while (tempNode.Parent<>nil )   do      begin
        aStr:= tempNode.Parent.Text+' \ '+ aStr;
        tempNode:=tempNode.Parent;
     end;

       ShowMessage( aStr);
    end;
  end;
end;


9把多层次的 XML 文档解析为 TreeView 显示

https://blog.csdn.net/pcplayer/article/details/129164849

procedure TForm1.Button1Click(Sender: TObject);
var
  Rootnode,node : IXMLNode;
  nodelist:IXMLNodeList;
  b,c,str, S: string;
  i, j:Integer;
  StartItemNode: IXMLNode;
  ANode: IXMLNode;
 
  TotalAmount, StartDate, EndDate, DepositDate: string;
  DT: Cardinal;
begin
  if OpenDialog1.Execute() then
  begin
    DT := GetTickCount;
    Screen.Cursor := crHourGlass;
    try
      XMLDocument1.LoadFromFile(OpenDialog1.FileName);
      XMLDocument1.Active := True;
 
      Rootnode := XMLDocument1.DocumentElement;
      TreeView1.Items.BeginUpdate;
      try
        CreateTreeView(RootNode, Treeview1.Items.GetFirstNode);
      finally
        TreeView1.Items.EndUpdate;
      end;
    finally
      Screen.Cursor := crDefault;
    end;
 
    DT := GetTickCount -DT;
    S := '执行时间 = ' + FloatToStr(DT/1000) + '';
    ShowMessage(S);
  end;
end;
 
procedure TForm1.CreateTreeView(ANode: IXMLNode; TreeNode: TTreeNode);
var
  ParentTreeNode, CurrentTreeNode: TTreeNode;
  i: Integer;
begin
  //采用递归,把一个多层次的 XML 变成 TreeView 显示。测试通过。
 
  if ANode.HasChildNodes then
  begin
    CurrentTreeNode := TreeView1.Items.AddChild(TreeNode, ANode.NodeName);
    ParentTreeNode := CurrentTreeNode;
    for i:=0 to ANode.ChildNodes.Count-1 do
    begin
      CreateTreeview(ANode.ChildNodes[i], ParentTreeNode);
    end;
  end
  else
  begin
    TreeView1.Items.AddChild(TreeNode, VarToStr(ANode.NodeValue));
  end;
end;