这是我在网上查的东东:由于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 ,需要这个修改后的控件,那位大哥能不能修改后发给我,或者告诉我具体的修改方法(本人比较菜,详细点)
,谢谢各位高手了!!!!!
在设计时因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 ,需要这个修改后的控件,那位大哥能不能修改后发给我,或者告诉我具体的修改方法(本人比较菜,详细点)
,谢谢各位高手了!!!!!
http://www.cnblogs.com/del/archive/2008/05/15/1198645.html
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.
http://www.cnblogs.com/del/archive/2008/05/15/1198645.html
万一的博客,有例子的,可以学习看一下。
错!Delphi自带的TTreeView里有复选框的功能!执行这句:
SetWindowLong(TreeView1.Handle, GWL_STYLE, GetWindowLong(TreeView1.Handle, GWL_STYLE) or TVS_CHECKBOXES);就有复选框了。但你如果想判断是否被选中等,用楼上几位提供的方法即可。