用stateindex来控制(两张图片,一张check,一张uncheck) 用mouseup来 procedure TfTree.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var tf:Ttreenode; begin inherited; tf:=self.GetNodeAt(x,y); if tf=nil then exit; if (x>=tf.Level*self.Indent) and (x<=tf.Level*self.Indent+12) then tf.StateIndex:=fokimg+fnoimg-tf.StateIndex;//改变stateindex图片 end;
myxfang的程序已经差不多了。不过我觉得,用MouseDown比MouseUp更好些。 procedure THlCheckPartTreeView.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var MyHitTest : THitTests; Node: TTreeNode; begin MyHitTest := GetHitTestInfoAt(X,Y); if htOnIcon in MyHitTest then begin Node := GetNodeAt(X, Y); // Do it yourself to toggle the imageindex end; end;
用TTreeView的StateImages属性和TTreeNode的StateIndex属性,这儿有个范本: Const ST_UNCHECK=0; ST_CHECK=1; ST_CHECKING=2;//设置当前结点及上下级的复选关系。 procedure TForm1.tvwMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var Node:TTreeNode; //将结点子树(含该结点)标为复选或清除状态 Procedure SetChildState(Node:TTreeNode;State:Integer); Begin Node.StateIndex:=State; Node:=Node.getFirstChild; while Node<>nil do begin Node.StateIndex:=State; IF Node.Count>0 Then SetChildState(Node,State); Node:=Node.getNextSibling; end; End; //返回结点子树(不含该结点)中的复选项数 Function GetCheckCount(Node:TTreeNode):Integer; var i:Integer; Begin i:=0; IF Node.Count>0 Then Begin Node:=Node.getFirstChild; While Node<>nil do Begin if Node.StateIndex=ST_CHECK then Inc(i); Inc(i,GetCheckCount(Node)); Node:=Node.getNextSibling; End; End; Result:=i; End; //返回结点子树(不含该结点)中的项数 Function GetChildCount(Node:TTreeNode):Integer; var i:Integer; Begin i:=0; IF Node.Count>0 Then Begin Node:=Node.getFirstChild; While Node<>nil do Begin Inc(i); Inc(i,GetCheckCount(Node)); Node:=Node.getNextSibling; End; End; Result:=i; End; //根据指定结点状态,设置父结点状态 Procedure SetParentState(Node:TTreeNode); var i,j:Integer; Begin Node:=Node.Parent; While Node<>nil Do Begin i:=GetChildCount(Node); j:=GetCheckcount(Node); if i=j then Node.StateIndex:=ST_CHECK else if (i>0) And (j=0) Then Node.StateIndex:=ST_UNCHECK else Node.StateIndex:=ST_CHECKING; Node:=Node.Parent; End; End; begin if (htOnStateIcon in tvw.GetHitTestInfoAt(X,Y)) And (Button=mbLeft) then Begin Node:=tvw.GetNodeAt(X,Y); Case Node.StateIndex Of ST_CHECK:Begin SetChildState(Node,ST_UNCHECK); end; ST_UNCHECK:Begin SetChildState(Node,ST_CHECK); End; ST_CHECKING:Begin SetChildState(Node,ST_UNCHECK); End; End; SetParentState(Node); End; end;
我看windows 98中的系统配置程序中就有这样的带checkbox的treeview,究竟怎么做呢?
用mouseup来
procedure TfTree.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
var tf:Ttreenode;
begin
inherited;
tf:=self.GetNodeAt(x,y);
if tf=nil then exit;
if (x>=tf.Level*self.Indent) and (x<=tf.Level*self.Indent+12) then
tf.StateIndex:=fokimg+fnoimg-tf.StateIndex;//改变stateindex图片
end;
procedure THlCheckPartTreeView.MouseDown(Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
MyHitTest : THitTests;
Node: TTreeNode;
begin
MyHitTest := GetHitTestInfoAt(X,Y);
if htOnIcon in MyHitTest then
begin
Node := GetNodeAt(X, Y);
// Do it yourself to toggle the imageindex
end;
end;
fnoimg 是uncheck状态的图像的iamgeindex值
Const
ST_UNCHECK=0;
ST_CHECK=1;
ST_CHECKING=2;//设置当前结点及上下级的复选关系。
procedure TForm1.tvwMouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
Node:TTreeNode;
//将结点子树(含该结点)标为复选或清除状态
Procedure SetChildState(Node:TTreeNode;State:Integer);
Begin
Node.StateIndex:=State;
Node:=Node.getFirstChild;
while Node<>nil do
begin
Node.StateIndex:=State;
IF Node.Count>0 Then SetChildState(Node,State);
Node:=Node.getNextSibling;
end;
End;
//返回结点子树(不含该结点)中的复选项数
Function GetCheckCount(Node:TTreeNode):Integer;
var
i:Integer;
Begin
i:=0;
IF Node.Count>0 Then
Begin
Node:=Node.getFirstChild;
While Node<>nil do
Begin
if Node.StateIndex=ST_CHECK then Inc(i);
Inc(i,GetCheckCount(Node));
Node:=Node.getNextSibling;
End;
End;
Result:=i;
End;
//返回结点子树(不含该结点)中的项数
Function GetChildCount(Node:TTreeNode):Integer;
var
i:Integer;
Begin
i:=0;
IF Node.Count>0 Then
Begin
Node:=Node.getFirstChild;
While Node<>nil do
Begin
Inc(i);
Inc(i,GetCheckCount(Node));
Node:=Node.getNextSibling;
End;
End;
Result:=i;
End; //根据指定结点状态,设置父结点状态
Procedure SetParentState(Node:TTreeNode);
var
i,j:Integer;
Begin
Node:=Node.Parent;
While Node<>nil Do
Begin
i:=GetChildCount(Node);
j:=GetCheckcount(Node);
if i=j then
Node.StateIndex:=ST_CHECK
else if (i>0) And (j=0) Then
Node.StateIndex:=ST_UNCHECK
else
Node.StateIndex:=ST_CHECKING;
Node:=Node.Parent;
End;
End;
begin
if (htOnStateIcon in tvw.GetHitTestInfoAt(X,Y)) And (Button=mbLeft) then
Begin
Node:=tvw.GetNodeAt(X,Y);
Case Node.StateIndex Of
ST_CHECK:Begin
SetChildState(Node,ST_UNCHECK);
end;
ST_UNCHECK:Begin
SetChildState(Node,ST_CHECK);
End;
ST_CHECKING:Begin
SetChildState(Node,ST_UNCHECK);
End;
End;
SetParentState(Node);
End;
end;