这是我在网上查的东东:由于Delphi自带的TTreeView里并没有复选框的功能。因此,必须重新设计控件。 
在设计时因TTreeView里有一个StateIndex和StateImages,而纵观TTreeView的代码可以知道它只是发布了一下TCustomTreeView定义并实现好的属性和方法而已。因此我们也选择TCustomTreeView为TCheckTree控件的祖先类。 
重要的实现技术为: 
procedure TCheckTree.WMPaint( var Msg: TWMPaint ); 
var 
I: Integer; 
begin 
for I := 0 to Items.Count - 1 do 
begin 
if not(Items[ I ].StateIndex in [Ord(csUnknown)..Ord(csPartiallyChecked)]) then 
Items[ I ].StateIndex := Ord(csUnchecked) //这里我修改了 
end; 
inherited; 
end; 
function TCheckTree.GetItemState( Node:TTreeNode ): TCheckCheckState; 
begin 
Result := TCheckCheckState( Node.StateIndex ); 
end; 
procedure TCheckTree.SetItemState( Node:TTreeNode; Value: TCheckCheckState ); 
begin 
if TCheckCheckState( Node.StateIndex ) <> Value then 
ChangeNodeCheckState( Node, Value ); 
end; 
procedure TCheckTree.StateChange( Node: TTreeNode; NewState: TCheckCheckState ); 
begin 
if Assigned( FOnStateChange ) then 
FOnStateChange( Self, Node, NewState ); 
end; 我刚开始学delphi ,需要这个修改后的控件,那位大哥能不能修改后发给我,或者告诉我具体的修改方法(本人比较菜,详细点)
,谢谢各位高手了!!!!!

解决方案 »

  1.   

    标准treeview也可以带复选框
    http://www.cnblogs.com/del/archive/2008/05/15/1198645.html
      

  2.   

    这个是我用的代码,拿过去建个组件包,然后安装一下就可以了。unit DLCheckboxTreeView;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ComCtrls, Commctrl, StdCtrls;
      
    type{ TDLCheckTreeView }  TDLStateChangeEvent = procedure (Sender: TObject; Node: TTreeNode;
        OldState, NewState: TCheckBoxState) of object;  TDLCheckTreeView = class(TTreeView)
      private
        { Private declarations }
        FStateImages: TImageList;
        FUpdateCount: Integer;
        FOnStateChange: TDLStateChangeEvent;
        function GetCheckBoxState(Node: TTreeNode): TCheckBoxState;
        procedure SetCheckBoxState(Node: TTreeNode;
          const Value: TCheckBoxState);
        function GetChecked(Node: TTreeNode): Boolean;
        procedure SetChecked(Node: TTreeNode; const Value: Boolean);
      protected
        { Protected declarations }
        procedure WndProc(var message: TMessage); override;
        procedure KeyPress(var Key: Char); override;
        procedure Loaded; override;
        function ToggleCheckedByPos(x, y: Integer): Boolean;
        function ToggleChecked(Node: TTreeNode): Boolean;
        procedure SyncChildNode(Node: TTreeNode);
        procedure SyncParentNode(Node: TTreeNode);
        procedure SetUpdateState(Updating: Boolean);
      public
        { Public declarations }
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure BeginUpdate;
        procedure EndUpdate;
        procedure SyncNodes;
        procedure SelectAll;
        procedure SelectNone;
        procedure SelectInvert;    property CheckBoxState[Node: TTreeNode]: TCheckBoxState read GetCheckBoxState
          write SetCheckBoxState;
        property Checked[Node: TTreeNode]: Boolean read GetChecked write SetChecked;
      published
        property OnStateChange: TDLStateChangeEvent read FOnStateChange write FOnStateChange;
      end;procedure Register;implementation{$R DLCheckboxTreeView.res}procedure Register;
    begin
      RegisterComponents('SQLDebug_Fan', [TDLCheckTreeView]);
    end;{ TDLCheckTreeView }constructor TDLCheckTreeView.Create(AOwner: TComponent);
    begin
      inherited;
      FStateImages := TImageList.CreateSize(16, 16);
      FStateImages.Handle := ImageList_LoadBitmap(hInstance, 'CNTREEVIEWSTATE',
        16, 0, clFuchsia);
      StateImages := FStateImages;
    end;destructor TDLCheckTreeView.Destroy;
    begin
      FStateImages.Free;
      inherited;
    end;procedure TDLCheckTreeView.Loaded;
    begin
      inherited Loaded;
      SyncNodes;
    end;function TDLCheckTreeView.GetCheckBoxState(Node: TTreeNode): TCheckBoxState;
    begin
      if Node.StateIndex in [1..3] then
        Result := TCheckBoxState(Node.StateIndex - 1)
      else
        Result := cbUnchecked;
    end;procedure TDLCheckTreeView.SetCheckBoxState(Node: TTreeNode;
      const Value: TCheckBoxState);
    var
      OldState: TCheckBoxState;
    begin
      // 不允许手工设置部分选择状态
      if (Node.StateIndex - 1 <> Ord(Value)) and (Value <> cbGrayed) then
      begin
        OldState := TCheckBoxState(Node.StateIndex - 1);
        Node.StateIndex := Ord(Value) + 1;
        if FUpdateCount = 0 then
        begin
          SyncChildNode(Node);
          SyncParentNode(Node);
          if Assigned(FOnStateChange) then
            FOnStateChange(Self, Node, OldState, Value);
        end;      
      end;
    end;function TDLCheckTreeView.GetChecked(Node: TTreeNode): Boolean;
    begin
      Result := GetCheckBoxState(Node) = cbChecked;
    end;procedure TDLCheckTreeView.SetChecked(Node: TTreeNode;
      const Value: Boolean);
    begin
      if Value then
        SetCheckBoxState(Node, cbChecked)
      else
        SetCheckBoxState(Node, cbUnchecked);
    end;function TDLCheckTreeView.ToggleChecked(Node: TTreeNode): Boolean;
    begin
      if Assigned(Node) then
      begin
        SetChecked(Node, not GetChecked(Node));
        Result := True;
      end
      else
        Result := False;
    end;function TDLCheckTreeView.ToggleCheckedByPos(x, y: Integer): Boolean;
    var
      Node: TTreeNode;
    begin
      Result := False;
      if htOnStateIcon in GetHitTestInfoAt(x, y) then
      begin
        Node := GetNodeAt(x, y);
        Result := ToggleChecked(Node);
      end;
    end;procedure TDLCheckTreeView.KeyPress(var Key: Char);
    begin
      if (Key = ' ') and Assigned(Selected) then
        ToggleChecked(Selected)
      else
        inherited;
    end;procedure TDLCheckTreeView.SyncNodes;
    var
      i: Integer;  function DoSyncNodeState(Node: TTreeNode): TCheckBoxState;
      var
        SelCount, UnSelCount, Count: Integer;
        ChildNode: TTreeNode;
      begin
        ChildNode := Node.GetFirstChild;
        if ChildNode <> nil then
        begin
          SelCount := 0;
          UnSelCount := 0;
          Count := 0;
          while ChildNode <> nil do
          begin
            if DoSyncNodeState(ChildNode) = cbChecked then
              Inc(SelCount)
            else if DoSyncNodeState(ChildNode) = cbUnchecked then
              Inc(UnSelCount);
            Inc(Count);
            ChildNode := Node.GetNextChild(ChildNode);
          end;      if SelCount = Count then
          begin
            if Node.StateIndex <> Ord(cbChecked) + 1 then
              Node.StateIndex := Ord(cbChecked) + 1;
          end
          else if UnSelCount = Count then
          begin
            if Node.StateIndex <> Ord(cbUnchecked) + 1 then
              Node.StateIndex := Ord(cbUnchecked) + 1;
          end
          else if Node.StateIndex <> Ord(cbGrayed) + 1 then
          begin
            Node.StateIndex := Ord(cbGrayed) + 1;
          end;
        end
        else if not (Node.StateIndex in [1..3]) then
        begin
          Node.StateIndex := Ord(cbUnchecked) + 1;
        end;    Result := GetCheckBoxState(Node);
      end;
    begin
      for i := 0 to Items.Count - 1 do
        DoSyncNodeState(Items[i]);
    end;// 同步子节点状态,子节点拷贝父节点状态
    procedure TDLCheckTreeView.SyncChildNode(Node: TTreeNode);
    var
      i: Integer;
    begin
      if Node.StateIndex <> Ord(cbGrayed) + 1 then
        for i := 0 to Node.Count - 1 do
        begin
          Node.Item[i].StateIndex := Node.StateIndex;
          SyncChildNode(Node.Item[i]);
        end;
    end;// 同步父节点状态, 父节点拷贝子节点状态
    procedure TDLCheckTreeView.SyncParentNode(Node: TTreeNode);
    var
      SelCount, UnSelCount, Count: Integer;
      ParentNode, ChildNode: TTreeNode;
    begin
      ParentNode := Node.Parent;
      if ParentNode <> nil then
      begin
        SelCount := 0;
        UnSelCount := 0;
        Count := 0;
        ChildNode := ParentNode.GetFirstChild;
        while ChildNode <> nil do
        begin
          if GetCheckBoxState(ChildNode) = cbChecked then
            Inc(SelCount)
          else if GetCheckBoxState(ChildNode) = cbUnchecked then
            Inc(UnSelCount);
          Inc(Count);
          ChildNode := ParentNode.GetNextChild(ChildNode);
        end;    if SelCount = Count then
        begin
          if ParentNode.StateIndex <> Ord(cbChecked) + 1 then
          begin
            ParentNode.StateIndex := Ord(cbChecked) + 1;
            SyncParentNode(ParentNode);
          end;
        end
        else if UnSelCount = Count then
        begin
          if ParentNode.StateIndex <> Ord(cbUnchecked) + 1 then
          begin
            ParentNode.StateIndex := Ord(cbUnchecked) + 1;
            SyncParentNode(ParentNode);
          end;
        end
        else if ParentNode.StateIndex <> Ord(cbGrayed) + 1 then
        begin
          ParentNode.StateIndex := Ord(cbGrayed) + 1;
          SyncParentNode(ParentNode);
        end;
      end;
    end;procedure TDLCheckTreeView.WndProc(var message: TMessage);
    begin
      case message.Msg of
        WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:
          begin
            if ToggleCheckedByPos(TWMLButtonDown(message).XPos, TWMLButtonDown(message).YPos)
              then
              Exit;
          end;
        WM_LBUTTONUP, WM_RBUTTONUP:
          begin
            if htOnStateIcon in GetHitTestInfoAt(TWMLButtonDown(message).XPos,
              TWMLButtonDown(message).YPos) then
              Exit;
          end;
      end;
      inherited WndProc(message);
    end;procedure TDLCheckTreeView.BeginUpdate;
    begin
      Items.BeginUpdate;
      if FUpdateCount = 0 then SetUpdateState(True);
      Inc(FUpdateCount);
    end;procedure TDLCheckTreeView.EndUpdate;
    begin
      Dec(FUpdateCount);
      if FUpdateCount = 0 then SetUpdateState(False);
      Items.EndUpdate;
    end;procedure TDLCheckTreeView.SetUpdateState(Updating: Boolean);
    begin
      if not Updating then
        SyncNodes;
    end;procedure TDLCheckTreeView.SelectAll;
    var
      Node: TTreeNode;
    begin
      Items.BeginUpdate;
      try
        Node := Items.GetFirstNode;
        while Node <> nil do
        begin
          Node.StateIndex := Ord(cbChecked) + 1;
          Node := Node.GetNext;
        end;
      finally
        Items.EndUpdate;
      end;          
    end;procedure TDLCheckTreeView.SelectNone;
    var
      Node: TTreeNode;
    begin
      Items.BeginUpdate;
      try
        Node := Items.GetFirstNode;
        while Node <> nil do
        begin
          Node.StateIndex := Ord(cbUnchecked) + 1;
          Node := Node.GetNext;
        end;
      finally
        Items.EndUpdate;
      end;
    end;procedure TDLCheckTreeView.SelectInvert;
    var
      Node: TTreeNode;
    begin
      Items.BeginUpdate;
      try
        Node := Items.GetFirstNode;
        while Node <> nil do
        begin
          if Node.StateIndex = Ord(cbUnchecked) + 1 then
            Node.StateIndex := Ord(cbChecked) + 1
          else if Node.StateIndex = Ord(cbChecked) + 1 then
            Node.StateIndex := Ord(cbUnchecked) + 1;
          Node := Node.GetNext;
        end;
      finally
        Items.EndUpdate;
      end;          
    end;end.
      

  3.   

    或者CnPack的组件包中也有一个带的CheckBox的TreeView,哪个有组件包,你安装一下就可以了。
      

  4.   

    标准treeview也可以带复选框 
    http://www.cnblogs.com/del/archive/2008/05/15/1198645.html
    万一的博客,有例子的,可以学习看一下。
      

  5.   


    错!Delphi自带的TTreeView里有复选框的功能!执行这句:
    SetWindowLong(TreeView1.Handle, GWL_STYLE, GetWindowLong(TreeView1.Handle, GWL_STYLE) or TVS_CHECKBOXES);就有复选框了。但你如果想判断是否被选中等,用楼上几位提供的方法即可。