加上checkbox的treeview控件源程序
时间:2010-10-16 来源:chulia
源代码如下: XTreeView.pas
unit XTreeView;
{
==============
TXTreeView 1.0 (1999-07-11)
==============
Enhaced TTreeView with 2- or 3-state checkboxes.
Freeware.
Copyright ?Roman Stedronsky 1999, [email protected]
All rights reserved. You may use this software in an application
without fee or royalty, provided this copyright notice remains intact.
types
-----
TCheckState defines 4 states for every node (No check,
Unchecked, Checked, Grayed)
public properties
-----------------
CheckStates[Index: integer] set/get the state for given node (by index)
published properties
--------------------
CheckBoxes when true, shows checkboxes
ThreeState when true, use 3-state cycle (un-checked-grayed)
when false, use 2-state cycle (unchecked-checked)
CheckBitmap defines visual appearance of checkboxes
(Width: 64 /4x16/,
type
TCheckState = (csNone, csUnchecked, csChecked, csGrayed);
TStateClickEvent = procedure(CheckState: TCheckState) of object;
TXTreeView = class(TCustomTreeView)
protected
{ internal variables }
FBitmap: TBitmap;
CheckStateImages: TImageList;
{ property variables }
FCheckBoxes: boolean;
FThreeState: boolean;
FStateClickEvent: TStateClickEvent;
{ property manipulation methods }
procedure FWriteCheckBoxes(Value: boolean);
function FReadCheckState(Index: integer): TCheckState;
procedure FWriteCheckState(Index: integer; Value: TCheckState);
procedure FWriteCheckBitmap(Value: TBitmap);
{ internal methods }
procedure ChangeCheckState(Node: TTreeNode);
procedure SetChildCS(Node: TTreeNode);
procedure SetParentCS(Node: TTreeNode);
function GetAllChildCS(Node:TTreeNode):integer;
procedure BitmapChanged(Sender: TObject);
public
{ overrided methods }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
property CheckStates[Index: integer]: TCheckState read FReadCheckState write FWriteCheckState;
published
property CheckBoxes: boolean read FCheckBoxes write FWriteCheckBoxes default true;
property ThreeState: boolean read FThreeState write FThreeState default false;
property CheckBitmap: TBitmap read FBitmap write FWriteCheckBitmap stored true default nil;
property OnStateClick: TStateClickEvent read FStateClickEvent write FStateClickEvent;
published
{ make TCustomTreeView propeties published (exclude StateImages) }
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 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;
property RightClickSelect;
property RowSelect;
property ShowButtons;
property ShowHint;
property ShowLines;
property ShowRoot;
property SortType;
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;
procedure Register;
implementation
{$R XTreeView.res}
const
cCheckStatesBitmap = 'CheckStatesBitmap ';
procedure Register;
begin
RegisterComponents( 'DETOOLS ', [TXTreeView]);
end;
{ property manipulation methods }
procedure TXTreeView.FWriteCheckBoxes(Value: boolean);
begin
FCheckBoxes := Value;
if FCheckBoxes then
StateImages := CheckStateImages
else
StateImages := nil;
end;
function TXTreeView.FReadCheckState(Index: integer): TCheckState;
begin
if (Index > -1) and (Index < Items.Count) then
if Items[Index].StateIndex = -1 then
Result := csNone
else
Result := TCheckState(Items[Index].StateIndex)
else
Result := csNone;
end;
procedure TXTreeView.FWriteCheckState(Index: integer; Value: TCheckState);
begin
if (Index > -1) and (Index < Items.Count) then
if Value = csNone then
Items[Index].StateIndex := -1
else
Items[Index].StateIndex := integer(Value);
end;
procedure TXTreeView.FWriteCheckBitmap(Value: TBitmap);
begin
if Value = nil then
begin
FBitmap.Handle := LoadBitmap(HInstance, cCheckStatesBitmap)
end
else
FBitmap.Assign(Value);
CheckStateImages.Clear; // Does Clear free memory or not?
CheckStateImages.Add(FBitmap, nil);
end;
{ internal methods }
procedure TXTreeView.BitmapChanged(Sender: TObject);
begin
CheckStateImages.Clear;
CheckStateImages.Add(FBitmap, nil);
end;
//ret values is 1 全部选中,2 全部未选中 3 部分选中
function TXTreeView.GetAllChildCS(Node:TTreeNode):integer;
var
ret:integer;
num,num1,num2,i:integer;
begin
num1:=0;
num2:=0;
num:=node.Count;
for i:=0 to num-1 do
begin
case node.Item[i].StateIndex of
1:inc(num1);
2:inc(num2);
end;
end;
if (num1=num)then
ret:=1
else
if (num2=num)then
ret:=2
else
ret:=3;
result:=ret;
end;
procedure TXTreeView.SetChildCS(Node: TTreeNode);
var
tempnode:ttreenode;
stateindex:integer;
begin
if (node <> nil) then
begin
stateindex:=node.StateIndex;
tempnode:=node.getFirstChild;
while(tempnode <> nil) do
begin
tempnode.StateIndex:=stateindex;
if (tempnode <> nil)and(tempnode.HasChildren) then
SetChildCS(tempnode);
tempnode:=tempnode.getNextSibling;
end;
end;
end;
procedure TXTreeView.SetParentCS(Node: TTreeNode);
var
tempnode:ttreenode;
begin
if (node <> nil) then
begin
tempnode:=node.GetPrev;
while(tempnode <> nil)do
begin
if (node.HasAsParent(tempnode))then
begin
//如果子节点当前状态为选中,那么搜索该父节点的所有子节点,
//如果已经全部选中,那末就将该父节点设为选中
//否则设置该父节点为灰色
//如果子节点当前状态为未选中,那么搜索该父节点所有子节点,
//如果全部未选中,那么设置该父节点为未选中
//否则设置为灰色
case node.StateIndex of
2:
begin
case GetAllChildCS(tempnode) of
1:
tempnode.StateIndex:=2;
2:
tempnode.StateIndex:=2;
3:
tempnode.StateIndex:=3;
end;
end;
1:
begin
case GetAllChildCS(tempnode) of
1:
tempnode.StateIndex:=1;
2,3:
tempnode.StateIndex:=3;
end;
end;
end;
end;
tempnode:=tempnode.GetPrev;
end;
end;
end;
procedure TXTreeView.ChangeCheckState(Node: TTreeNode);
begin
if CheckStates[Node.AbsoluteIndex] = csUnchecked then
CheckStates[Node.AbsoluteIndex] := csChecked
else
if CheckStates[Node.AbsoluteIndex] = csChecked then
begin
CheckStates[Node.AbsoluteIndex] := csUnchecked
{
if FThreeState then
CheckStates[Node.AbsoluteIndex] := csGrayed
else
CheckStates[Node.AbsoluteIndex] := csUnchecked
}
end
else
CheckStates[Node.AbsoluteIndex] := csUnchecked;
SetChildCS(node);
SetParentCS(Node);
end;
{ overrided methods }
constructor TXTreeView.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
CheckStateImages := TImageList.Create(Self);
FBitmap := TBitmap.Create;
FBitmap.OnChange := BitmapChanged;
FBitmap.Handle := LoadBitmap(HInstance, cCheckStatesBitmap);
StateImages := CheckStateImages;
FThreeState := false;
CheckBoxes := true;
ParentColor := False;
TabStop := True;
end;
destructor TXTreeView.Destroy;
begin
FBitmap.Free;
CheckStateImages.Free;
inherited Destroy;
end;
procedure TXTreeView.CNNotify(var Message: TWMNotify);
var
Node: TTreeNode;
Point: TPoint;
Position: DWORD;
begin
case message.nmhdr.code of
NM_CLICK:
begin
Position := GetMessagePos;
Point.x := LoWord(Position);
Point.y := HiWord(Position);
Point := ScreenToClient(Point);
Node := GetNodeAt(Point.x, Point.y);
if (Node <> nil) then
begin
if htOnStateIcon in GetHitTestInfoAt(Point.x, Point.y) then
begin
ChangeCheckState(Node);
if Assigned(FStateClickEvent) then
FStateClickEvent(CheckStates[Node.AbsoluteIndex]);
end;
end;
end;
end;
inherited;
end;
end.
相关阅读 更多 +










