使用ImageList,将CheckBox的图片根据状态显示到不同的节点就可以,如果希望切换某个节点的选择状态的同时更新其父节点及子节点的状态,那么稍许复杂点,这里是我以前一个项目中使用的代码:procedure TfrmA4.RefreshTreeViewStatus(const AAuthority:String); procedure SetNodeStatus(ANode:TTreeNode;Select:Boolean); begin if Select then begin UpdateNodeStatus(ANode,1); end else begin UpdateNodeStatus(ANode,0); end; end; begin trv1.Items.BeginUpdate; try SetNodeStatus(trv1.Items[2],Copy(AAuthority,1,1) = '1'); SetNodeStatus(trv1.Items[3],Copy(AAuthority,2,1) = '1'); SetNodeStatus(trv1.Items[4],Copy(AAuthority,3,1) = '1'); SetNodeStatus(trv1.Items[6],Copy(AAuthority,4,1) = '1'); SetNodeStatus(trv1.Items[7],Copy(AAuthority,5,1) = '1'); SetNodeStatus(trv1.Items[8],Copy(AAuthority,6,1) = '1'); SetNodeStatus(trv1.Items[9],Copy(AAuthority,7,1) = '1'); SetNodeStatus(trv1.Items[11],Copy(AAuthority,8,1) = '1'); SetNodeStatus(trv1.Items[12],Copy(AAuthority,9,1) = '1'); SetNodeStatus(trv1.Items[13],Copy(AAuthority,10,1) = '1'); SetNodeStatus(trv1.Items[15],Copy(AAuthority,11,1) = '1'); SetNodeStatus(trv1.Items[16],Copy(AAuthority,12,1) = '1'); SetNodeStatus(trv1.Items[17],Copy(AAuthority,13,1) = '1'); SetNodeStatus(trv1.Items[18],Copy(AAuthority,14,1) = '1'); SetNodeStatus(trv1.Items[19],Copy(AAuthority,15,1) = '1'); finally trv1.Items.EndUpdate; end; end;procedure TfrmA4.UpdateNodeStatus(const ANode:TTreeNode;const ASelectStatus:Integer; const ASeekParent:Boolean;const ASeekChild:Boolean); var NodeTmp:TTreeNode; SelectedCount,VSelectedCount:Integer; begin if (ASelectStatus=0) and (Integer(ANode.Data)<>0) then begin ANode.Data:=Pointer(0); ANode.ImageIndex:=0; ANode.SelectedIndex:=0; end else if (ASelectStatus=1) and (Integer(ANode.Data)<>1) then begin ANode.Data:=Pointer(1); ANode.ImageIndex:=1; ANode.SelectedIndex:=1; end else if (ASelectStatus=2) and (Integer(ANode.Data)<>2) then begin ANode.Data:=Pointer(2); ANode.ImageIndex:=2; ANode.SelectedIndex:=2; end; //update all child nodes if (ASeekChild) and (ASelectStatus<>2) then begin NodeTmp:=ANode.GetFirstChild(); if Assigned(NodeTmp) then begin repeat UpdateNodeStatus(NodeTmp,ASelectStatus,false,true); NodeTmp:=NodeTmp.GetNextSibling(); until not Assigned(NodeTmp); end; end; //update parent node if ASeekParent then begin NodeTmp:=ANode.Parent; if Assigned(NodeTmp) then begin NodeTmp:=NodeTmp.GetFirstChild(); SelectedCount:=0; VSelectedCount:=0; repeat if Integer(NodeTmp.Data)=1 then begin Inc(SelectedCount); end else if Integer(NodeTmp.Data)=2 then begin Inc(VSelectedCount); end; NodeTmp:=NodeTmp.GetNextSibling(); until not Assigned(NodeTmp); if SelectedCount=ANode.Parent.Count then begin UpdateNodeStatus(ANode.Parent,1,true,false); end else if (SelectedCount>0) or (VSelectedCount>0) then begin UpdateNodeStatus(ANode.Parent,2,true,false); end else begin UpdateNodeStatus(ANode.Parent,0,true,false); end; end; end; end;procedure TfrmA4.trv1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var HitTest:THitTests; Item:TTreeNode; begin if not edt1.Enabled then begin //not in the edit mode exit; end; HitTest:=trv1.GetHitTestInfoAt(X,Y); if htOnIcon in HitTest then begin Item:=trv1.GetNodeAt(X,Y); if Assigned(Item) then begin trv1.Items.BeginUpdate; try if (Integer(Item.Data)=1) or (Integer(Item.Data)=2) then begin UpdateNodeStatus(Item,0); end else begin UpdateNodeStatus(Item,1); end; finally trv1.Items.EndUpdate; end; end; end; end;
procedure SetNodeStatus(ANode:TTreeNode;Select:Boolean);
begin
if Select then begin
UpdateNodeStatus(ANode,1);
end
else begin
UpdateNodeStatus(ANode,0);
end;
end;
begin
trv1.Items.BeginUpdate;
try
SetNodeStatus(trv1.Items[2],Copy(AAuthority,1,1) = '1');
SetNodeStatus(trv1.Items[3],Copy(AAuthority,2,1) = '1');
SetNodeStatus(trv1.Items[4],Copy(AAuthority,3,1) = '1');
SetNodeStatus(trv1.Items[6],Copy(AAuthority,4,1) = '1');
SetNodeStatus(trv1.Items[7],Copy(AAuthority,5,1) = '1');
SetNodeStatus(trv1.Items[8],Copy(AAuthority,6,1) = '1');
SetNodeStatus(trv1.Items[9],Copy(AAuthority,7,1) = '1');
SetNodeStatus(trv1.Items[11],Copy(AAuthority,8,1) = '1');
SetNodeStatus(trv1.Items[12],Copy(AAuthority,9,1) = '1');
SetNodeStatus(trv1.Items[13],Copy(AAuthority,10,1) = '1');
SetNodeStatus(trv1.Items[15],Copy(AAuthority,11,1) = '1');
SetNodeStatus(trv1.Items[16],Copy(AAuthority,12,1) = '1');
SetNodeStatus(trv1.Items[17],Copy(AAuthority,13,1) = '1');
SetNodeStatus(trv1.Items[18],Copy(AAuthority,14,1) = '1');
SetNodeStatus(trv1.Items[19],Copy(AAuthority,15,1) = '1');
finally
trv1.Items.EndUpdate;
end;
end;procedure TfrmA4.UpdateNodeStatus(const ANode:TTreeNode;const ASelectStatus:Integer;
const ASeekParent:Boolean;const ASeekChild:Boolean);
var
NodeTmp:TTreeNode;
SelectedCount,VSelectedCount:Integer;
begin
if (ASelectStatus=0) and (Integer(ANode.Data)<>0) then begin
ANode.Data:=Pointer(0);
ANode.ImageIndex:=0;
ANode.SelectedIndex:=0;
end
else if (ASelectStatus=1) and (Integer(ANode.Data)<>1) then begin
ANode.Data:=Pointer(1);
ANode.ImageIndex:=1;
ANode.SelectedIndex:=1;
end
else if (ASelectStatus=2) and (Integer(ANode.Data)<>2) then begin
ANode.Data:=Pointer(2);
ANode.ImageIndex:=2;
ANode.SelectedIndex:=2;
end;
//update all child nodes
if (ASeekChild) and (ASelectStatus<>2) then begin
NodeTmp:=ANode.GetFirstChild();
if Assigned(NodeTmp) then begin
repeat
UpdateNodeStatus(NodeTmp,ASelectStatus,false,true);
NodeTmp:=NodeTmp.GetNextSibling();
until not Assigned(NodeTmp);
end;
end;
//update parent node
if ASeekParent then begin
NodeTmp:=ANode.Parent;
if Assigned(NodeTmp) then begin
NodeTmp:=NodeTmp.GetFirstChild();
SelectedCount:=0;
VSelectedCount:=0;
repeat
if Integer(NodeTmp.Data)=1 then begin
Inc(SelectedCount);
end
else if Integer(NodeTmp.Data)=2 then begin
Inc(VSelectedCount);
end;
NodeTmp:=NodeTmp.GetNextSibling();
until not Assigned(NodeTmp);
if SelectedCount=ANode.Parent.Count then begin
UpdateNodeStatus(ANode.Parent,1,true,false);
end
else if (SelectedCount>0) or (VSelectedCount>0) then begin
UpdateNodeStatus(ANode.Parent,2,true,false);
end
else begin
UpdateNodeStatus(ANode.Parent,0,true,false);
end;
end;
end;
end;procedure TfrmA4.trv1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
HitTest:THitTests;
Item:TTreeNode;
begin
if not edt1.Enabled then begin //not in the edit mode
exit;
end;
HitTest:=trv1.GetHitTestInfoAt(X,Y);
if htOnIcon in HitTest then begin
Item:=trv1.GetNodeAt(X,Y);
if Assigned(Item) then begin
trv1.Items.BeginUpdate;
try
if (Integer(Item.Data)=1) or (Integer(Item.Data)=2) then begin
UpdateNodeStatus(Item,0);
end
else begin
UpdateNodeStatus(Item,1);
end;
finally
trv1.Items.EndUpdate;
end;
end;
end;
end;