放一个ImageList,在里面放两张复选框的图像,将TreeView1的Images属性设为ImageList1,
然后设置每个结点的ImageIndex

解决方案 »

  1.   

    ImageList1,放两张图片('√', 'X')
    就可以了
      

  2.   

    试试这个控件
    unit CheckTV;interfaceuses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      ComCtrls, StdCtrls;type  TCheckKind = (ckNone, ckCheck, ckRadio, ckGroup);
      TCheckFlatness = (cfAlwaysFlat, cfAlways3d, cfHotTrack);  TCheckTreeNode = class;  TCheckTreeView = class(TCustomTreeView)
      private
        FDesignInteractive: Boolean;
        FNodeProps: Boolean;
        FGrayedIsChecked: Boolean;
        FStateImages: TImageList;
        FFlatness: TCheckFlatness;
        function GetChecked(Node: TTreeNode): Boolean;
        procedure SetChecked(Node: TTreeNode; Value: Boolean);
        function GetState(Node: TTreeNode): TCheckBoxState;
        procedure SetState(Node: TTreeNode; Value: TCheckBoxState);
        function GetKind(Node: TTreeNode): TCheckKind;
        procedure SetKind(Node: TTreeNode; Value: TCheckKind);
        procedure SetFlatness(const Value: TCheckFlatness);
        function GetNodeEnabled(Node: TTreeNode): Boolean;
        procedure SetNodeEnabled(Node: TTreeNode; const Value: Boolean);
        procedure ReadData(Stream: TStream);
        procedure WriteData(Stream: TStream);
        procedure CMMouseLeave(var Message: TMessage); message CM_MOUSELEAVE;
        procedure CMDesignHitTest(var Message: TCMDesignHitTest); message
          CM_DESIGNHITTEST;
        procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
        procedure WMLButtonDblClk(var Message: TWMLButtonDblClk); message
          WM_LBUTTONDBLCLK;
        {<<add by eric
        procedure SetOthersCheck(Node: TTreeNode);
        procedure SetSonCheck(Node: TTreeNode);
        procedure SetParentCheck(Node: TTreeNode);
        function GetStateBySon(Node: TTreeNode): TCheckBoxState;
        //}
      protected
        FHoverCache: TCheckTreeNode;
        procedure ToggleNode(Node: TCheckTreeNode); dynamic;
        procedure Change(Node: TTreeNode); override;
        procedure CreateCheckMarks; dynamic;
        function CreateNode: TTreeNode; override;
        procedure DefineProperties(Filer: TFiler); override;
        procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y:
          Integer); override;
        procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
        procedure Loaded; override;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
        procedure MakeRadioGroup(Node: TTreeNode);
        property Checked[Node: TTreeNode]: Boolean read GetChecked write SetChecked;
        property State[Node: TTreeNode]: TCheckBoxState read GetState write
          SetState;
        property CheckKind[Node: TTreeNode]: TCheckKind read GetKind write SetKind;
        property NodeEnabled[Node: TTreeNode]: Boolean read GetNodeEnabled write
          SetNodeEnabled;
      published
        property A0About: Boolean read FDesignInteractive write FDesignInteractive stored False;
        property A0NodeProps: Boolean read FNodeProps write FNodeProps stored False;
        property Align;
        property Anchors;
        property AutoExpand;
        property BiDiMode;
        property BorderStyle;
        property BorderWidth;
        property ChangeDelay;
        property Color;
        property Ctl3D;
        property Constraints;
        property DragKind;
        property DragCursor;
        property DragMode;
        property Enabled;
        property Font;
        property Flatness: TCheckFlatness read FFlatness write SetFlatness;
        property GrayedIsChecked: Boolean read FGrayedIsChecked write
          FGrayedIsChecked;
        property HideSelection;
        property HotTrack;
        property Images;
        property Indent;
        property Items;
        property ParentBiDiMode;
        property ParentColor default False;
        property ParentCtl3D;
        property ParentFont;
        property ParentShowHint;
        property PopupMenu;
        property ReadOnly default True;
        property RightClickSelect;
        property RowSelect;
        property ShowButtons;
        property ShowHint;
        property ShowLines;
        property ShowRoot;
        property SortType;
        //property StateImages;
        property TabOrder;
        property TabStop default True;
        property ToolTips;
        property Visible;
        property OnChange;
        property OnChanging;
        property OnClick;
        property OnCollapsing;
        property OnCollapsed;
        property OnCompare;
        property OnCustomDraw;
        property OnCustomDrawItem;
        property OnDblClick;
        property OnDeletion;
        property OnDragDrop;
        property OnDragOver;
        property OnEdited;
        property OnEditing;
        property OnEndDock;
        property OnEndDrag;
        property OnEnter;
        property OnExit;
        property OnExpanding;
        property OnExpanded;
        property OnGetImageIndex;
        property OnGetSelectedIndex;
        property OnKeyDown;
        property OnKeyPress;
        property OnKeyUp;
        property OnMouseDown;
        property OnMouseMove;
        property OnMouseUp;
        property OnStartDock;
        property OnStartDrag;
      end;  TCheckTreeNode = class(TTreeNode)
      private
        FReflexChildren: Boolean;
        FCheckKind: TCheckKind;
        FCache: TCheckBoxState;
        FEnabled: Boolean;
        FReflexParent: Boolean;
        function IsEqual(Node: TTreeNode): Boolean;
        function GetItemIndex: Integer;
        function GetChecked: Boolean;
        procedure SetChecked(Value: Boolean);
        procedure SetCheckKind(Value: TCheckKind);
        procedure SetEnabled(Value: Boolean);
        function GetState: TCheckBoxState;
        procedure SetState(Value: TCheckBoxState);
        procedure SetItemIndex(Value: Integer);
        procedure SetReflexChildren(Value: Boolean);
        procedure SetReflexParent(Value: Boolean);
        procedure ReadSelf(Stream: TStream);
        procedure WriteSelf(Stream: TStream);
      protected
        procedure InternalSetState(Value: TCheckBoxState;
          CheckChildren: Boolean = True; CheckParent: Boolean = True);
        procedure DoCheckChildren(Cur: TCheckBoxState);
        procedure DoCheckParent(Cur: TCheckBoxState);
        procedure UpdateHotTrack(Hover: Boolean); virtual;
      public
        procedure AfterConstruction; override;
        procedure MakeRadioGroup;
        procedure Assign(Source: TPersistent); override;
        property Checked: Boolean read GetChecked write SetChecked;
        property CheckKind: TCheckKind read FCheckKind write SetCheckKind;
        property CheckState: TCheckBoxState read GetState write SetState;
        property Enabled: Boolean read FEnabled write SetEnabled;
        property ItemIndex: Integer read GetItemIndex write SetItemIndex;
        property ReflexChildren: Boolean read FReflexChildren write
          SetReflexChildren;
        property ReflexParent: Boolean read FReflexParent write SetReflexParent;
      end;  ECheckTreeViewError = class(Exception);
      EIndexError = class(ECheckTreeViewError);resourcestring
      SIndexError = 'Tree node index (%d) out of range';
      SInvalidKind = 'Trying to set index (%d) of non-radio item';procedure Register;implementation{ TCheckTreeView }type
      PCheckNodeData = ^TCheckNodeData;
      TCheckNodeData = packed record
        Kind: TCheckKind;
        Enabled: Boolean;
      end;procedure TCheckTreeView.CMDesignHitTest(var Message: TCMDesignHitTest);
    var
      N: TTreeNode;
    begin
      Message.Result := 0;
      if FDesignInteractive then
      begin
        N := GetNodeAt(Message.XPos, Message.YPos);
        if N <> nil then
          Message.Result := Integer(N.DisplayRect(True).Right > Message.XPos);
      end;
    end;procedure TCheckTreeView.CMMouseLeave(var Message: TMessage);
    begin
      if FHoverCache <> nil then FHoverCache.UpdateHotTrack(False);
      FHoverCache := nil;
      inherited;
    end;constructor TCheckTreeView.Create(AOwner: TComponent);
    begin
      inherited Create(AOwner);
      //ReadOnly := True;
    end;procedure TCheckTreeView.CreateCheckMarks;
    const
      R: TRect = (Left: 2; Top: 2; Right: 15; Bottom: 15);
    var
      Bmp, M: TBitmap;  procedure Add(MaskColor: TColor = clWhite);
      begin
        FStateImages.AddMasked(Bmp, MaskColor);
      end;begin
      if FStateImages = nil then Exit;
      Items.BeginUpdate;
      Bmp := TBitmap.Create;
      M := TBitmap.Create;
      try
        Bmp.Width := 16;
        Bmp.Height := 16;
        M.Width := 16;
        M.Height := 16;    { Add stub image }
        {1} Add;    { Add flat images }
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONCHECK or
          DFCS_FLAT);
        {2} Add;
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONCHECK or
          DFCS_FLAT or DFCS_CHECKED);
        {3} Add;
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONCHECK or
          DFCS_FLAT or DFCS_CHECKED or DFCS_BUTTON3STATE);
        {4} Add;
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOIMAGE or
          DFCS_FLAT);
        DrawFrameControl(M.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOMASK or
          DFCS_FLAT);
        {5} FStateImages.Add(Bmp, M);
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOIMAGE or
          DFCS_FLAT or DFCS_CHECKED);
        DrawFrameControl(M.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOMASK or
          DFCS_FLAT or DFCS_CHECKED);
        {6} FStateImages.Add(Bmp, M);    { Add 3d images }
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONCHECK);
        {7} Add;
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONCHECK or
          DFCS_CHECKED);
        {8} Add;
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONCHECK or
          DFCS_CHECKED or DFCS_BUTTON3STATE);
        {9} Add;
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOIMAGE);
        DrawFrameControl(M.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOMASK);
        {10} FStateImages.Add(Bmp, M);
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOIMAGE or
          DFCS_CHECKED);
        DrawFrameControl(M.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOMASK or
          DFCS_CHECKED);
        {11} FStateImages.Add(Bmp, M);    { Add disabled images }
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONCHECK
          or DFCS_INACTIVE);
        {12} Add;
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONCHECK or
          DFCS_CHECKED or DFCS_INACTIVE);
        {13} Add;
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONCHECK or
          DFCS_CHECKED or DFCS_BUTTON3STATE or DFCS_INACTIVE);
        {14} Add;
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOIMAGE
          or DFCS_INACTIVE);
        DrawFrameControl(M.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOMASK
          or DFCS_INACTIVE);
        {15} FStateImages.Add(Bmp, M);
        DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOIMAGE or
          DFCS_CHECKED or DFCS_INACTIVE);
        DrawFrameControl(M.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONRADIOMASK or
          DFCS_CHECKED or DFCS_INACTIVE);
        {16} FStateImages.Add(Bmp, M);  finally
        M.Free;
        Bmp.Free;
        Items.EndUpdate;
      end;
    end;function TCheckTreeView.CreateNode: TTreeNode;
    begin
      Result := TCheckTreeNode.Create(Items);
      with TCheckTreeNode(Result) do
      begin
        CheckKind := ckNone;
        ReflexChildren := True;
        ReflexParent := True;
      end;
    end;destructor TCheckTreeView.Destroy;
    begin
      inherited Destroy;
    end;function TCheckTreeView.GetChecked(Node: TTreeNode): Boolean;
    begin
      Result := TCheckTreeNode(Node).Checked
    end;function TCheckTreeView.GetNodeEnabled(Node: TTreeNode): Boolean;
    begin
      Result := TCheckTreeNode(Node).Enabled;
    end;function TCheckTreeView.GetKind(Node: TTreeNode): TCheckKind;
    begin
      Result := TCheckTreeNode(Node).CheckKind
    end;function TCheckTreeView.GetState(Node: TTreeNode): TCheckBoxState;
    begin
      Result := TCheckTreeNode(Node).CheckState
    end;procedure TCheckTreeView.Loaded;
    begin
      FStateImages := TImageList.Create(Self);
      StateImages := FStateImages;
      CreateCheckMarks;
      inherited Loaded;
      FDesignInteractive := True;
    end;procedure TCheckTreeView.MakeRadioGroup(Node: TTreeNode);
    begin
      TCheckTreeNode(Node).MakeRadioGroup
    end;procedure TCheckTreeView.MouseDown(Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    begin
      if (Button = mbLeft) and (htOnStateIcon in GetHitTestInfoAt(X, Y)) then
        ToggleNode(TCheckTreeNode(GetNodeAt(X, Y)));
      inherited MouseDown(Button, Shift, X, Y);
    end;procedure TCheckTreeView.MouseMove(Shift: TShiftState; X, Y: Integer);
    var
      N: TCheckTreeNode;
    begin
      if HotTrack and (Flatness = cfHotTrack) then
      begin
        N := TCheckTreeNode(GetNodeAt(X, Y));
        if (FHoverCache <> N) then
        begin
          if FHoverCache <> nil then FHoverCache.UpdateHotTrack(False);
          if N <> nil then N.UpdateHotTrack(True);
          FHoverCache := N;
        end;
      end;
      inherited MouseMove(Shift, X, Y);
    end;procedure TCheckTreeView.SetChecked(Node: TTreeNode; Value: Boolean);
    begin
      TCheckTreeNode(Node).Checked := Value;
    end;procedure TCheckTreeView.SetNodeEnabled(Node: TTreeNode; const Value: Boolean);
    begin
      TCheckTreeNode(Node).Enabled := Value
    end;procedure TCheckTreeView.SetFlatness(const Value: TCheckFlatness);
    var
      I: Integer;
    begin
      if FFlatness <> Value then
      begin
        FFlatness := Value;
        for I := 0 to Items.Count - 1 do
          TCheckTreeNode(Items[I]).InternalSetState(
            TCheckTreeNode(Items[I]).GetState, False, False)
      end;
    end;procedure TCheckTreeView.SetKind(Node: TTreeNode; Value: TCheckKind);
    begin
      TCheckTreeNode(Node).CheckKind := Value
    end;procedure TCheckTreeView.SetState(Node: TTreeNode; Value: TCheckBoxState);
    begin
      TCheckTreeNode(Node).CheckState := Value;
    //  SetOthersCheck(Node);
    end;procedure TCheckTreeView.WMLButtonDblClk(var Message: TWMLButtonDblClk);
    begin
      if not (htOnStateIcon in GetHitTestInfoAt(Message.XPos, Message.YPos)) then
        inherited;
    end;procedure TCheckTreeView.Change(Node: TTreeNode);
    begin
      if csDesigning in ComponentState then GetParentForm(Self).Designer.Modified;
      inherited Change(Node);
    end;procedure TCheckTreeView.WMKeyDown(var Message: TWMKeyDown);
    begin
      if Message.CharCode = VK_SPACE then
      begin
        ToggleNode(TCheckTreeNode(Selected));
        Message.Result := 0;
      end
      else
        inherited;
    end;procedure TCheckTreeView.ToggleNode(Node: TCheckTreeNode);
    var
      PrevCheck: TCheckBoxState;
      Frm: TCustomForm;
    begin
      if (Node <> nil) and Node.Enabled then
      begin
        if Node.CheckKind = ckCheck then
        begin
          PrevCheck := Node.GetState;
          if PrevCheck <> cbChecked then
          begin
            Node.InternalSetState(cbChecked);
            if Node.GetState = PrevCheck then Node.InternalSetState(cbUnchecked);
          end
          else
            Node.InternalSetState(cbUnchecked);
        end
        else if Node.CheckKind = ckRadio then
          Node.Checked := True;
        if csDesigning in ComponentState then
        begin
          Frm := GetParentForm(Self);
          if Frm <> nil then
            Frm.Designer.Modified
        end;
      end;
    end;procedure TCheckTreeView.DefineProperties(Filer: TFiler);  function WriteNodes: Boolean;
      var
        I: Integer;
        Nodes: TTreeNodes;
      begin
        Nodes := TTreeNodes(Filer.Ancestor);
        if Nodes = nil then
          Result := Items.Count > 0
        else if Nodes.Count <> Items.Count then
          Result := True
        else
        begin
          Result := False;
          for I := 0 to Items.Count - 1 do
          begin
            Result := not TCheckTreeNode(Items.Item[I]).IsEqual(Nodes[I]);
            if Result then Break;
          end
        end;
      end;begin
      inherited DefineProperties(Filer);
      Filer.DefineBinaryProperty('CheckNodesData', ReadData, WriteData, WriteNodes);
    end;procedure TCheckTreeView.ReadData(Stream: TStream);
    var
      I: Integer;
    begin
      for I := 0 to Items.Count - 1 do
        TCheckTreeNode(Items[I]).ReadSelf(Stream);
    end;procedure TCheckTreeView.WriteData(Stream: TStream);
    var
      I: Integer;
    begin
      for I := 0 to Items.Count - 1 do
        TCheckTreeNode(Items[I]).WriteSelf(Stream);
    end;{<<add by ericprocedure TCheckTreeView.SetOthersCheck(Node: TTreeNode);
    begin
      if Node = nil then exit;
      SetSonCheck(Node);
      SetParentCheck(Node);
    end;procedure TCheckTreeView.SetParentCheck(Node: TTreeNode);
    begin
      if not Assigned(Node.Parent) then exit;
      TCheckTreeNode(Node.Parent).CheckState := GetStateBySon(Node);
    end;procedure TCheckTreeView.SetSonCheck(Node: TTreeNode);
    var
      ANode: TCheckTreeNode;
    begin
      ANode := TCheckTreeNode(Node.getFirstChild);  if (ANode = nil) or (TCheckTreeNode(Node.getFirstChild).CheckState = cbGrayed) then exit;  while ANode <> nil do
      begin
        ANode.CheckState := TCheckTreeNode(Node).CheckState;
        ANode := TCheckTreeNode(ANode.getNextSibling);
      end;
    end;function TCheckTreeView.GetStateBySon(Node: TTreeNode): TCheckBoxState;
    var
      ANode: TCheckTreeNode;
      iUnchecked, iChecked, iGrayed: Integer;
    begin
      iUnchecked := 0; iChecked := 0; iGrayed := 0;  ANode := TCheckTreeNode(Node.getFirstChild);  while ANode <> nil do
      begin
        case ANode.CheckState of
          cbUnchecked: inc(iUnchecked);
          cbChecked: inc(iChecked);
          cbGrayed: begin inc(iGrayed); break; end;
        end;
        ANode := TCheckTreeNode(ANode.getNextSibling);
      end;  if iGrayed > 0 then
      begin
        Result := cbGrayed;
        exit;
      end;  if iChecked = Node.Count then
      begin
        Result := cbChecked;
        exit;
      end;  if iUnchecked = Node.Count then
      begin
        Result := cbUnchecked;
        exit;
      end;  Result := cbGrayed;
    end;
    //}{ TCheckTreeNode }const
      StateIndexes: array[TCheckKind, TCheckBoxState] of Integer =
        ((-1, -1, -1), (1, 2, 3), (4, 5, 4), (-1, -1, -1));procedure TCheckTreeNode.AfterConstruction;
    begin
      FEnabled := True;
      FCheckKind := ckCheck;
      FReflexChildren := True;
      FReflexParent := True;
    end;procedure TCheckTreeNode.Assign(Source: TPersistent);
    var
      Node: TCheckTreeNode;
    begin
      inherited Assign(Source);
      if Source is TCheckTreeNode then
      begin
        Node := TCheckTreeNode(Source);
        StateIndex := Node.StateIndex;
        FCheckKind := Node.CheckKind;
        ReflexChildren := Node.ReflexChildren;
        ReflexParent := Node.ReflexParent;
      end;
    end;procedure TCheckTreeNode.DoCheckChildren(Cur: TCheckBoxState);
    var
      I: Integer;
      MustCheckParent: Boolean;
      N, D: TCheckTreeNode;
    begin
      MustCheckParent := False;
      D := nil;
      if (FCheckKind in [ckCheck, ckGroup]) and FReflexChildren and (Cur <> cbGrayed)
        then
      begin
        for I := 0 to Count - 1 do
        begin
          N := TCheckTreeNode(Item[I]);
          if N.Enabled then
            N.InternalSetState(Cur, True, False)
          else
          begin
            MustCheckParent := True;
            D := N;
          end;
        end;
        if MustCheckParent then D.DoCheckParent(Cur);
      end;
    end;procedure TCheckTreeNode.DoCheckParent(Cur: TCheckBoxState);
    var
      I: Integer;
      Ch, Un: Boolean;
    begin
      Ch := True;
      Un := True;
      if (FCheckKind in [ckCheck, ckGroup]) and FReflexParent and (Parent <> nil)
        then
        with TCheckTreeNode(Parent) do
        begin
          for I := 0 to Count - 1 do
          begin
            if TCheckTreeNode(Item[I]).FCheckKind in [ckCheck, ckGroup] then
              case TCheckTreeNode(Item[I]).GetState of
                cbUnchecked: Ch := False;
                cbChecked:
                  Un := False
              else
                begin
                  Ch := False;
                  Un := False;
                  Break;
                end
              end;
            if not Ch and not Un then Break;
          end;
          if Ch then
            InternalSetState(cbChecked, False, True)
          else if Un then
            InternalSetState(cbUnchecked, False, True)
          else
            InternalSetState(cbGrayed, False, True)
        end;
    end;function TCheckTreeNode.GetChecked: Boolean;
    var
      S: TCheckBoxState;
    begin
      S := GetState;
      Result := S = cbChecked;
      if (FCheckKind in [ckCheck, ckGroup]) and
        TCheckTreeView(TreeView).FGrayedIsChecked and (S = cbGrayed) then
        Result := True
    end;function TCheckTreeNode.GetItemIndex: Integer;
    begin
      for Result := 0 to Count - 1 do
        with TCheckTreeNode(Item[Result]) do
          if (FCheckKind = ckRadio) and Checked then Exit;
      Result := -1;
    end;function TCheckTreeNode.GetState: TCheckBoxState;
    begin
      case StateIndex of
        -1..1, 4, 6, 9, 11, 14: Result := cbUnchecked;
        2, 5, 7, 10, 12, 15:
          Result := cbChecked
      else
        Result := cbGrayed
      end;
      if FCheckKind = ckGroup then Result := FCache;
    end;procedure TCheckTreeNode.InternalSetState(Value: TCheckBoxState;
      CheckChildren, CheckParent: Boolean);
    var
      I: Integer;
      Node: TCheckTreeNode;
      SI: Integer;
    begin
      SI := StateIndexes[FCheckKind, Value];
      if SI > 0 then
        if not Enabled then
          StateIndex := SI + 10
        else if TCheckTreeView(TreeView).Flatness = cfAlways3d then
          StateIndex := SI + 5
        else
          StateIndex := SI;
      UpdateHotTrack(TCheckTreeView(TreeView).FHoverCache = Self);
      if FCheckKind = ckGroup then FCache := Value;
      if (FCheckKind = ckRadio) and (Value = cbChecked) then
        for I := 0 to Parent.Count - 1 do
        begin
          Node := TCheckTreeNode(Parent.Item[I]);
          if (Node <> Self) and (Node.FCheckKind = ckRadio) then
            Node.InternalSetState(cbUnchecked, False, False);
        end;
      if CheckChildren then DoCheckChildren(Value);
      if CheckParent then DoCheckParent(Value);
    end;const
      BoolChecks: array[Boolean] of TCheckBoxState = (cbUnchecked, cbChecked);function TCheckTreeNode.IsEqual(Node: TTreeNode): Boolean;
    begin
      Result := (Text = Node.Text) and (Data = Node.Data);
    end;procedure TCheckTreeNode.MakeRadioGroup;
    var
      I: Integer;
    begin
      CheckKind := ckNone;
      for I := Count - 1 downto 0 do
        if not Item[I].HasChildren then
          with TCheckTreeNode(Item[I]) do
          begin
            CheckKind := ckRadio;
            //Checked := True
          end;
    end;procedure TCheckTreeNode.ReadSelf(Stream: TStream);
    var
      Data: TCheckNodeData;
    begin
      Stream.ReadBuffer(Data, SizeOf(Data));
      FCheckKind := Data.Kind;
      FEnabled := Data.Enabled;
    end;procedure TCheckTreeNode.SetChecked(Value: Boolean);
    begin
      if GetState <> BoolChecks[Value] then
        InternalSetState(BoolChecks[Value])
    end;procedure TCheckTreeNode.SetCheckKind(Value: TCheckKind);
    begin
      if FCheckKind <> Value then
      begin
        FCheckKind := Value;
        if FCheckKind = ckNone then
          StateIndex := -1
        else if FCheckKind = ckGroup then
        begin
          FCache := GetState;
          StateIndex := -1;
        end
        else
          InternalSetState(GetState);
      end;
    end;procedure TCheckTreeNode.SetEnabled(Value: Boolean);
    var
      I: Integer;
    begin
      if FEnabled <> Value then
      begin
        FEnabled := Value;
        InternalSetState(GetState, False, False);
      end;
      for I := 0 to Count - 1 do
        TCheckTreeNode(Item[I]).Enabled := Value;
    end;procedure TCheckTreeNode.SetItemIndex(Value: Integer);
    begin
      if Value > Count then raise EIndexError.CreateFmt(SIndexError, [Value]);
      if TCheckTreeNode(Item[Value]).FCheckKind <> ckRadio then
        EIndexError.CreateFmt(SInvalidKind, [Value]);
      TCheckTreeNode(Item[Value]).SetState(cbChecked);
    end;procedure TCheckTreeNode.SetReflexChildren(Value: Boolean);
    begin
      if FReflexChildren <> Value then
      begin
        FReflexChildren := Value;
        DoCheckChildren(GetState)
      end;
    end;procedure TCheckTreeNode.SetReflexParent(Value: Boolean);
    begin
      if FReflexParent <> Value then
      begin
        FReflexParent := Value;
        DoCheckParent(GetState);
      end;
    end;procedure TCheckTreeNode.SetState(Value: TCheckBoxState);
    begin
      if Value <> GetState then
        InternalSetState(Value)
    end;procedure TCheckTreeNode.UpdateHotTrack(Hover: Boolean);
    begin
      if (FCheckKind in [ckCheck, ckRadio]) and Enabled and
        (TCheckTreeView(TreeView).Flatness <> cfAlways3d) then
      begin
        if Hover then
          StateIndex := StateIndexes[FCheckKind, GetState] + 5
        else
          StateIndex := StateIndexes[FCheckKind, GetState];
      end;
    end;procedure TCheckTreeNode.WriteSelf(Stream: TStream);
    var
      Data: TCheckNodeData;
    begin
      Data.Kind := CheckKind;
      Data.Enabled := Enabled;
      Stream.WriteBuffer(Data, SizeOf(Data));
    end;procedure Register;
    begin
      RegisterComponents('MyWin32', [TCheckTreeView]);
    end;end.
      

  3.   

    Bellamy的控件不知道怎么用啊,在哪个属性里设置啊?我怎么看着连multiselect都没有呢?
      

  4.   

    procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
    var
      p: TPoint;
    begin
      GetCursorPos(p);
      p := TreeView1.ScreenToClient(p);;
      if htOnIcon in TreeView1.GetHitTestInfoAt(p.x, p.y) then
      begin
        if Node.SelectedIndex = 0 then
        begin
          Node.ImageIndex := 1;
          Node.SelectedIndex := 1;
        end
        else begin
          Node.ImageIndex := 0;
          Node.SelectedIndex := 0;
        end;
      end;
    end;