关于delphi treeview加选择框
大家好!前面看了万一老师的博客,用
SetWindowLong(H, GWL_STYLE, GetWindowLong(H, GWL_STYLE) or TVS_CHECKBOXES)
实现在treeview前加选择框。试了一下,可以,不过我有一个疑问,如何用代码控制将某个节点置为“选中”或“未选中”状态呢?我的目的是想,在某个节点状态改变(选中或未选中)时,自动改变父节点和子节点的状态。
谢谢!
[解决办法]
把treeview和imagelist结合起来使用,很方便的就可以达到楼主想要的效果。
[解决办法]
就是修改TreeView的StateIndex来改变选中未选中,ImageList中添加2个图标,一个是不打勾的,一个打勾的,然后改StateIndex就可以
[解决办法]
1stClass 里面有这样的组件
[解决办法]
曾经写过的一个控件
- Delphi(Pascal) code
unit CheckedTreeView;interfaceuses 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.