给 TTreeView 添加复选框(转)

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

给 TTreeView 添加复选框(转)

 

 

在Delphi10.3运行成功

1.引用单元

2.定义私有过程

3.过程体代码

4.点击连选处理

5.生成节点

6.查看是否选中


//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;

 

在Delphi10.3运行成功

1.引用单元

2.定义私有过程

3.过程体代码

4.点击连选处理

5.生成节点

6.查看是否选中

 

上一篇:【WPF】WPF TreeView 右对齐


下一篇:Kendo UI TreeView 常见情况