我的控件是treeview 的扩展版 checktree ,就是treeview带复选框;
目的:
  1、如何找出树叶子结点?
  2、如果某结点的子结点有被选结点但未全选,如何选其为“实心”状态,同时,如果全选,则其为“被选”状态?

解决方案 »

  1.   

    1.TTreeNode.parent();方法可以对比某节点的父节点
      或:TTreeNode.HasChildren也可以判断当前节点有没有子点节.
    2.自己画或是设置其节点状态;
      

  2.   

    //参考如下代码uses CommCtrl;function TreeNodeGetChecked(mTreeNode: TTreeNode): Boolean;
    var
      vTVItem: TTVItem;
    begin
      Result := False;
      if not Assigned(mTreeNode) or not Assigned(mTreeNode.TreeView) then Exit;
      vTVItem.mask := TVIF_STATE;
      vTVItem.hItem := mTreeNode.ItemId;
      if TreeView_GetItem(mTreeNode.TreeView.Handle, vTVItem) then
        Result := (vTVItem.State and IndexToStateImageMask(2)) > 0; //0: None 1: False 2: True
    end; { TreeNodeGetChecked }function TreeNodeSetChecked(mTreeNode: TTreeNode; mChecked: Boolean): Boolean;
    var
      vTVItem: TTVItem;
    begin
      Result := False;
      if not Assigned(mTreeNode) or not Assigned(mTreeNode.TreeView) then Exit;  vTVItem.mask := TVIF_STATE;
      vTVItem.hItem := mTreeNode.ItemId;
      TreeView_GetItem(mTreeNode.TreeView.Handle, vTVItem);
      if not TreeView_GetItem(mTreeNode.TreeView.Handle, vTVItem) then Exit;
      vTVItem.stateMask := TVIS_STATEIMAGEMASK;
      vTVItem.state := IndexToStateImageMask(Succ(Ord(mChecked)));
      Result := TreeView_SetItem(mTreeNode.TreeView.Handle, vTVItem);
    end; { TreeNodeSetChecked }procedure TForm1.FormCreate(Sender: TObject);
    begin
      SetWindowLong(TreeView1.Handle, GWL_STYLE,
        GetWindowLong(TreeView1.Handle, GWL_STYLE) or TVS_CHECKBOXES);
    end;procedure TForm1.TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
      procedure pSelect(mTreeNode: TTreeNode; mChecked: Boolean);
      var
        I: Integer;
      begin
        TreeNodeSetChecked(mTreeNode, mChecked);
        for I := 0 to mTreeNode.Count - 1 do pSelect(mTreeNode[I], mChecked);
      end;  procedure pSelectYes(mTreeNode: TTreeNode);
      begin
        while Assigned(mTreeNode.Parent) and
          not TreeNodeGetChecked(mTreeNode.Parent) do
        begin
          TreeNodeSetChecked(mTreeNode.Parent, True);
          mTreeNode := mTreeNode.Parent;
        end;
      end;  procedure pSelectNo(mTreeNode: TTreeNode);
      var
        I: Integer;
      begin
        if Assigned(mTreeNode.Parent) and TreeNodeGetChecked(mTreeNode.Parent) then
        begin
          for I := 0 to mTreeNode.Parent.Count - 1 do
            if TreeNodeGetChecked(mTreeNode.Parent[I]) then Exit;
          TreeNodeSetChecked(mTreeNode.Parent, False);
          pSelectNo(mTreeNode.Parent);
        end;
      end;var
      vTreeNode: TTreeNode;
    begin
      if not (htOnStateIcon in TTreeView(Sender).GetHitTestInfoAt(X, Y)) then Exit;
      vTreeNode := TTreeView(Sender).GetNodeAt(X, Y);
      pSelect(vTreeNode, TreeNodeGetChecked(vTreeNode));
      if not TreeNodeGetChecked(vTreeNode) then
        pSelectNo(vTreeNode)
      else pSelectYes(vTreeNode);
    end;
      

  3.   

    ///参考以下这个
    procedure TForm1.TvUserListToggleCheckbox(
      TreeView: TfcCustomTreeView; Node: TfcTreeNode);
    var CurNode, ParentNode, GrandSonNode: TfcTreeNode;
      flg1: boolean;
    begin
      inherited;
      if Node.CheckboxType<>tvctCheckbox then Exit;
      with TreeView do begin
        if Node.Checked then //判断父是否为灰
        begin
          ParentNode:= Node.Parent; //父;
          if ParentNode<>nil then
          begin
            GrandSonNode := ParentNode.GetFirstChild; //遍历子树;
            flg1 := false;
            while GrandSonNode<>nil do
            begin
              if (not GrandSonNode.Checked) or (GrandSonNode.Grayed) then //true,有未选中
                flg1 := true;
              if flg1 then //已有、退出loop;
                GrandSonNode := nil
              else
                GrandSonNode := GrandSonNode.GetNextSibling;
            end;
            if flg1 then
              ParentNode.Grayed := true
            else
              ParentNode.Grayed := false;
            ParentNode.Checked := true; //return;
          end;
        end;
        if Node.checked and (not Node.Grayed) then //选中/不灰,子全选
        begin
          CurNode := Node.GetFirstChild; //子全选;
          while CurNode<>nil do
          begin
            CurNode.Checked := true; //return;
            CurNode := CurNode.GetNextSibling;
          end;
        end;
        if not Node.Checked then //未选中
        begin
          CurNode := Node.GetFirstChild;
          while CurNode<>nil do
          begin
            CurNode.Checked := false;
            CurNode := CurNode.GetNextSibling;
          end;
        end;
        if not Node.Checked then //判断父是否为灰
        begin
          ParentNode := Node.Parent; //父;
          if ParentNode<>nil then
          begin
            GrandSonNode := ParentNode.GetFirstChild; //遍历子树;
            flg1 := false;
            while GrandSonNode<>nil do
            begin
              if (GrandSonNode.Checked) or (GrandSonNode.Grayed) then //true,有选中
                flg1 := true;
              if flg1 then //已有、退出loop;
                GrandSonNode := nil
              else
                GrandSonNode := GrandSonNode.GetNextSibling;
            end;
            if flg1 then
            begin
              ParentNode.Grayed := true;
              ParentNode.Checked := true; //return;
            end
            else
            begin
              ParentNode.Grayed := false;
              ParentNode.Checked := false; //return;
            end;
          end;
        end;
      end;
    end;
      

  4.   

    To  
     zswang(伴水清清)(专家门诊清洁工) (
    也许是我太笨了把,你的代码我看的很费劲,觉得挺深的!关键是没有注释,不太好看,不过也谢谢了!To
    hongqi162(失踪的月亮)
    谢谢你的代码!我比较笨,一直到现在才弄出来!当然也谢谢你的注释!!注释太有用了!