大家好!前面看了万一老师的博客,用
SetWindowLong(H, GWL_STYLE, GetWindowLong(H, GWL_STYLE) or TVS_CHECKBOXES)
实现在treeview前加选择框。试了一下,可以,不过我有一个疑问,如何用代码控制将某个节点置为“选中”或“未选中”状态呢?我的目的是想,在某个节点状态改变(选中或未选中)时,自动改变父节点和子节点的状态。
谢谢!
SetWindowLong(H, GWL_STYLE, GetWindowLong(H, GWL_STYLE) or TVS_CHECKBOXES)
实现在treeview前加选择框。试了一下,可以,不过我有一个疑问,如何用代码控制将某个节点置为“选中”或“未选中”状态呢?我的目的是想,在某个节点状态改变(选中或未选中)时,自动改变父节点和子节点的状态。
谢谢!
解决方案 »
- Delphi 如何调用WebService 我要最详细的说明!
- stringgrid中的递增
- 两个问题:TreeView/XML和ClientDataSet?
- 关于调试?
- 请问怎样Import Components ---- 初级问题
- Tidestone formula one 6.0?
- 一个记录对象(type RMyRecord = record) 似乎不需要实例化?
- 请问如何实现form上的系统关闭窗口的按钮点击后出现提示对话框?
- Delphi依时利二次开发,读卡基本信息失败!
- 一个关于DLL的问题,请大家帮忙,万分感谢!!
- 关于Idhttp+线程类的疑问。
- 这个是个什么问题呢?刚接触delphi就遇到了
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, Commctrl;type
TTVCheckChangedEvent = procedure(Sender: TObject; Node: TTreeNode; Checked: boolean) of object;
TCheckedTreeView = class(TTreeView)
private
{ Private declarations } protected
{ Protected declarations }
F_OnNodeCheckChanged: TTVCheckChangedEvent; //当一个Node的Checked属性发生变化后触发
F_CheckedNodeList: TList; //纪录所有被Checked的节点
F_CheckBoxes: Boolean; //是否显示CheckBox
//某个Node被选中或反选后触发
procedure Do_NodeChecked(node: TTreeNode; checked: Boolean);virtual;
procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
procedure SetCheckBoxes(value: Boolean);
function GetNodeFromItem(const Item: TTVItem): TTreeNode;
procedure Delete(Node: TTreeNode); override;
public
{ Public declarations }
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
function NodeChecked(node: TTreeNode): boolean;
procedure CheckNode(Node :TTreeNode; Checked :Boolean);
published
{ Published declarations }
property OnNodeCheckedChanged: TTVCheckChangedEvent read F_OnNodeCheckChanged write F_OnNodeCheckChanged;
property CheckBoxes: boolean read F_CheckBoxes write SetCheckBoxes;
end;function IsNodeChecked(node: TTreeNode): boolean;
procedure SetNodeChecked(Node :TTreeNode; Checked :Boolean);
procedure Register;implementationconst
TVIS_CHECKED = $2000;
TVIS_UNCHECKED = $1000;
TVS_CHECKBOXES = $0100;procedure Register;
begin
RegisterComponents('Samples', [TCheckedTreeView]);
end;
procedure SetComCtlStyle(Ctl: TWinControl; Value: Integer; UseStyle: Boolean);
var
Style: Integer;
begin
if Ctl.HandleAllocated then
begin
Style := GetWindowLong(Ctl.Handle, GWL_STYLE);
if not UseStyle then
Style := Style and (not Value)
else
Style := Style or Value;
SetWindowLong(Ctl.Handle, GWL_STYLE, Style);
end;
end;function IsNodeChecked(node: TTreeNode): boolean;
var
TvItem:TTVItem;
begin
TvItem.Mask := TVIF_STATE;
TvItem.hItem := Node.ItemId;
TreeView_GetItem(Node.TreeView.Handle, TvItem);
Result := (TvItem.State and TVIS_CHECKED) = TVIS_CHECKED;
end;procedure SetNodeChecked(Node :TTreeNode; Checked :Boolean);
var
TvItem:TTVItem;
begin
FillChar(TvItem, SizeOf(TvItem), 0);
with TvItem do
begin
hItem :=Node.ItemId;
Mask := TVIF_STATE;
StateMask := TVIS_STATEIMAGEMASK;
if Checked then
TvItem.State:= (TvItem.State and (not TVIS_UNCHECKED)) or TVIS_CHECKED
else
TvItem.State:=(TvItem.State and (not TVIS_CHECKED)) or TVIS_UNCHECKED;
TreeView_SetItem(Node.TreeView.Handle, TvItem);
end;
end;{ TCheckedTreeView }procedure TCheckedTreeView.CNNotify(var Message: TWMNotify);
var
bOriginalChecked: Boolean;
bCurrentChecked: Boolean;
nIndex: Integer;
node: TTreeNode;
begin
inherited;
With Message do
begin
case NMHdr^.code of
TVN_GETDISPINFO:
begin
with PTVDispInfo(NMHdr)^ do
begin
Node := GetNodeFromItem(item);
bCurrentChecked:= IsNodeChecked(node);
nIndex:= F_CheckedNodeList.IndexOf(node);
if nIndex >= 0 then
bOriginalChecked:= true
else
bOriginalChecked:= false; if bOriginalChecked <> bCurrentChecked then
begin
if bCurrentChecked then
F_CheckedNodeList.Add(node)
else
F_CheckedNodeList.Delete(nIndex);
Do_NodeChecked(node, bCurrentChecked);
end ;
end ;
end;
end ; //case
end;
end ;
constructor TCheckedTreeView.Create(AOwner: TComponent);
begin
inherited;
F_CheckBoxes:= false;
F_CheckedNodeList:= TList.Create;
end;destructor TCheckedTreeView.Destroy;
begin
F_CheckedNodeList.Clear;
F_CheckedNodeList.Free;
inherited;end;function TCheckedTreeView.NodeChecked(node: TTreeNode): boolean;
begin
Result:= IsNodeChecked(node);
end ;procedure TCheckedTreeView.CheckNode(Node :TTreeNode; Checked :Boolean);
var
nIndex: Integer;
begin
SetNodeChecked(node, checked);
nIndex:= F_CheckedNodeList.IndexOf(node);
if checked and (nIndex< 0) then
begin
F_CheckedNodeList.Add(Node);
Do_NodeChecked(node, checked);
end
else if (not checked) and (nIndex>=0 ) then
begin
F_CheckedNodeList.Delete(nIndex);
Do_NodeChecked(node, checked);
end ;
end ;procedure TCheckedTreeView.Do_NodeChecked(node: TTreeNode;
checked: Boolean);
begin
if F_CheckBoxes then
if Assigned(F_OnNodeCheckChanged) then
F_OnNodeCheckChanged(self,node, checked);
end;function TCheckedTreeView.GetNodeFromItem(const Item: TTVItem): TTreeNode;
begin
Result := nil;
if Items <> nil then
with Item do
if (state and TVIF_PARAM) <> 0 then Result := Pointer(lParam)
else Result := Items.GetNode(hItem);
end;procedure TCheckedTreeView.SetCheckBoxes(value: Boolean);
var
nIndex: Integer;
TvItem:TTVItem;
begin
if Value<> F_CheckBoxes then
begin
F_CheckBoxes:= value;
if value then
SetComCtlStyle(Self,TVS_CHECKBOXES,True)
else
begin
SetComCtlStyle(Self,TVS_CHECKBOXES,False);
F_CheckedNodeList.Clear ;
//Update all nodes' state to remove the boxes
for nIndex := 0 to Items.Count -1 do
begin
FillChar(TvItem, SizeOf(TvItem), 0);
with TvItem do
begin
hItem :=Items.Item[nIndex].ItemId;
Mask := TVIF_STATE;
StateMask := TVIS_STATEIMAGEMASK;
TreeView_GetItem(Handle, TvItem);
TVItem.State:= TVItem.state and (Not TVIS_UNCHECKED) and (Not TVIS_CHECKED);
TreeView_SetItem(Handle, TvItem);
end; end ;
end ; end ;
end ;procedure TCheckedTreeView.Delete(Node: TTreeNode);
var
nIndex: Integer;
begin
nIndex:= F_CheckedNodeList.IndexOf(node);
if nIndex >= 0 then
F_CheckedNodeList.Delete(nIndex);
inherited;
end;end.