TListView控件能否在各columns中加入TcheckBox控件,以支持在一行中对各列进行不定项选择 ( 积分: 100 )

  • 主题发起人 主题发起人 chinagale
  • 开始时间 开始时间
C

chinagale

Unregistered / Unconfirmed
GUEST, unregistred user!
在开发管理软件时,一个功能往往有好几种权限,如采购订单的权限:
察看权、新增权、打印权、修改权、审核权等。
现在想有一个控件,比如象listview的控件一样,在一行的各列中通过checkbox能
授予不同的权限,但问题是Tlistview控件中columns的各列没有
checkbox控件,这样就不能实现在一行中对各列进行多选,也就没法
实现权限功能。
您是否有这样的控件呢?或能提供源代码呢?特别感谢。
 
唉,10天了,无人答。
 
CXGRID可以加CHECKBOX,只要设置属性就可以了
 
TListView 没有试过,估计也很难了,除非楼主自己继承 TListView 写一个。
还是建议楼主用第三方组件,如 Raize 的 TRzCheckTree。
 
尊敬的风铃夜思雨、 liyinwei:谢谢你们的回复,这是我的第一个问题。我先按你们的意思试试。谢谢。(不过,raize我是知道的,对我现在的程序不是很适合,因为每一个功能项都需要点击开才行,用在我的程序里不直观、不方便,记得以前金蝶就是用的您所说的这种控件。)
 
给你一个控件

unit CheckTV;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, StdCtrls, DsgnIntf;

type

TCheckKind = (ckNone, ckCheck, ckRadio, ckGroup);
TCheckFlatness = (cfAlwaysFlat, cfAlways3d, cfHotTrack);

TCheckTreeNode = class;

TNotifyNodeChecked = procedure(Sender: TObject;Checked: Boolean) of object;

TCheckTreeView = class(TCustomTreeView)
private
FDesignInteractive: Boolean;
FNodeProps: Boolean;
FGrayedIsChecked: Boolean;
FAllowGrayed: Boolean;
public
FStateImages: TImageList;
private
FFlatness: TCheckFlatness;
FDisableCheck:Boolean;
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;
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;
// procedure Expand(Node: TTreeNode); override;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure InitCheck;
procedure MakeRadioGroup(Node: TTreeNode);

property DisableCheck:Boolean read FDisableCheck write FDisableCheck;

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;

// add by Li Minghua at 2001/09/17
// activity the Event NodeCheck by Event MouseDown .
private
FOnNodeChecked:TNotifyNodeChecked;

published
property OnNodeChecked: TNotifyNodeChecked read FOnNodeChecked write FOnNodeChecked;
property AllowGrayed: Boolean read FAllowGrayed write FAllowGrayed;


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 OnAdvancedCustomDraw;
property OnAdvancedCustomDrawItem;
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;
FTag:Integer;
FTextTag:string;

// FHasSetChildren: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;
property Tag:Integer read FTag write FTag;
property TextTag:string read FTextTag write FTextTag;
end;

ECheckTreeViewError = class(Exception);
EIndexError = class(ECheckTreeViewError);

procedure Register;

resourcestring
SIndexError = 'Tree node index (%d) out of range';
SInvalidKind = 'Trying to set index (%d) of non-radio item';


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 or DFCS_FLAT);
{12} Add;
DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONCHECK or
DFCS_CHECKED or DFCS_INACTIVE or DFCS_FLAT);
{13} Add;
DrawFrameControl(Bmp.Canvas.Handle, R, DFC_BUTTON, DFCS_BUTTONCHECK or
DFCS_CHECKED or DFCS_BUTTON3STATE or DFCS_INACTIVE or DFCS_FLAT);
{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.InitCheck;
begin
FStateImages := TImageList.Create(Self);
StateImages := FStateImages;
CreateCheckMarks;
end;

procedure TCheckTreeView.Loaded;
begin
InitCheck;
{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 begin
ToggleNode(TCheckTreeNode(GetNodeAt(X, Y)));
if Assigned(FOnNodeChecked) then FOnNodeChecked(TCheckTreeNode(GetNodeAt(X, Y)),
TCheckTreeNode(GetNodeAt(X, Y)).Checked);
end;
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;

// add by Li Minghua at 2001/11/20
if Assigned(FOnNodeChecked) then FOnNodeChecked(TCheckTreeNode(Node),
TCheckTreeNode(Node).Checked);

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).InternalSetState(
TCheckTreeNode(Items).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
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));

// add by Li Minghua at 2001.11.20
if Assigned(FOnNodeChecked) then FOnNodeChecked(TCheckTreeNode(Selected),
TCheckTreeNode(Selected).Checked);

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) or (Node.CheckKind = ckNone) then
begin
Node.CheckKind := ckCheck;
PrevCheck := Node.GetState;
case PrevCheck of
cbUnchecked:
if FAllowGrayed then Node.InternalSetState(cbGrayed) else Node.InternalSetState(cbChecked);
cbChecked: Node.InternalSetState(cbUnChecked);
cbGrayed: Node.InternalSetState(cbChecked);
end;
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).IsEqual(Nodes);
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).ReadSelf(Stream);
end;

procedure TCheckTreeView.WriteData(Stream: TStream);
var
I: Integer;
begin
for I := 0 to Items.Count - 1 do
TCheckTreeNode(Items).WriteSelf(Stream);
end;

//procedure TCheckTreeView.Expand(Node: TTreeNode);
//var
// i:Integer;
//begin
// inherited;
{if TCheckTreeNode(Node).FHasSetChildren then Exit;
if TCheckTreeNode(Node).CheckKind<>ckCheck then Exit;
case TCheckTreeNode(Node).CheckState of
cbUnchecked:
begin
for i:=0 to Node.Item.Count-1 do
if TCheckTreeNode(Node.Item).CheckKind=ckCheck then
TCheckTreeNode(Node.Item).CheckState:=
end;
cbChecked:
cbGrayed: ;
end;}
//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);
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).FCheckKind in [ckCheck, ckGroup] then
case TCheckTreeNode(Item).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);
if (Node <> Self) and (Node.FCheckKind = ckRadio) then
Node.InternalSetState(cbUnchecked, False, False);
end;
if not TCheckTreeView(TreeView).DisableCheck then begin
if CheckChildren then DoCheckChildren(Value);
if CheckParent then DoCheckParent(Value);
end;
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.HasChildren then
with TCheckTreeNode(Item) 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).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('Fenet-Royalstone', [TCheckTreeView]);
end;

end.
 
尊敬的SandWater:谢谢回复。您的代码,我估计与liyinwei说的差不多,是一个树型节点,再点开是很多子节点,每个子节点都有一个checkbox,是吧?如果是这样的话,功能是可以实现,但不方便,因为每个功能节点都需要维护员去点开才可以显示子功能节点,不象ListView一样在一行的各列中载入一个Tcheckbox组件。这样不直观,不方便,如果让程序自动显示子节点,数据又太多,不能一眼看到很多功能,要用鼠标拖上拖下的。所以最好是在Listview的subitem中均能有一个Checkbox功能。
再次对您的帮助表示感谢。
 
后退
顶部