以下本人在Delphi XE2 进行编写并通过
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.Menus, Vcl.StdCtrls, Data.DB, Data.Win.ADODB, CommCtrl, Vcl.Grids, Vcl.DBGrids; type TForm1 = class(TForm) tv1: TTreeView; btn1: TButton; mmo1: TMemo; con1: TADOConnection; qry1: TADOQuery; btn5: TButton; btn2: TButton; qry2: TADOQuery; btn3: TButton; dlgSave1: TSaveDialog; mm1: TMainMenu; N86: TMenuItem; N87: TMenuItem; N88: TMenuItem; N84: TMenuItem; N83: TMenuItem; N85: TMenuItem; N91: TMenuItem; N92: TMenuItem; N93: TMenuItem; N1: TMenuItem; N78: TMenuItem; N79: TMenuItem; N80: TMenuItem; N81: TMenuItem; N82: TMenuItem; N90: TMenuItem; N2: TMenuItem; N57: TMenuItem; N59: TMenuItem; N58: TMenuItem; N60: TMenuItem; N61: TMenuItem; N95: TMenuItem; N62: TMenuItem; N63: TMenuItem; N64: TMenuItem; N65: TMenuItem; N66: TMenuItem; N67: TMenuItem; N69: TMenuItem; N70: TMenuItem; N71: TMenuItem; N72: TMenuItem; N103: TMenuItem; N75: TMenuItem; N73: TMenuItem; N74: TMenuItem; N76: TMenuItem; N77: TMenuItem; N3: TMenuItem; N53: TMenuItem; N54: TMenuItem; N55: TMenuItem; N56: TMenuItem; N4: TMenuItem; N42: TMenuItem; N44: TMenuItem; N52: TMenuItem; N45: TMenuItem; N46: TMenuItem; N47: TMenuItem; N48: TMenuItem; N49: TMenuItem; N50: TMenuItem; N51: TMenuItem; N5: TMenuItem; N32: TMenuItem; N33: TMenuItem; N34: TMenuItem; N35: TMenuItem; N36: TMenuItem; N37: TMenuItem; N38: TMenuItem; N39: TMenuItem; N40: TMenuItem; N41: TMenuItem; N6: TMenuItem; N29: TMenuItem; N31: TMenuItem; N28: TMenuItem; N89: TMenuItem; N7: TMenuItem; N25: TMenuItem; N96: TMenuItem; N30: TMenuItem; N100: TMenuItem; N27: TMenuItem; N99: TMenuItem; N26: TMenuItem; N101: TMenuItem; N102: TMenuItem; N8: TMenuItem; N21: TMenuItem; N22: TMenuItem; N23: TMenuItem; N24: TMenuItem; N97: TMenuItem; N43: TMenuItem; N98: TMenuItem; N9: TMenuItem; N16: TMenuItem; N20: TMenuItem; N14: TMenuItem; N15: TMenuItem; N17: TMenuItem; N18: TMenuItem; N19: TMenuItem; N94: TMenuItem; N10: TMenuItem; N11: TMenuItem; N12: TMenuItem; N13: TMenuItem; btn4: TButton; procedure aaaaa(mMenu: TMenuItem; nNode: TTreeNodes;p_node: TTreeNode); procedure btn1Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure btn5Click(Sender: TObject); procedure tv1Click(Sender: TObject); procedure btn2Click(Sender: TObject); procedure btn3Click(Sender: TObject); procedure btn4Click(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; Rights, MenuCaptions : string; implementation {$R *.dfm} const TVIS_CHECKED = $2000; //检查某个节点是否被 选中 function IsChecked(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 SetChecked(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 :=TVIS_CHECKED else TvItem.State := TVIS_CHECKED shr 1; TreeView_SetItem(Node.TreeView.Handle, TvItem); end; end; // 检查对节点中所有子节点 选中 或 未选中 状态 procedure tvToggleCheckbox(TreeView: TTreeView;Node: TTreeNode ;isclick :boolean=false); var CurNode, ParentNode, GrandSonNode,sonNode: TTreeNode; flg1: boolean; begin CurNode :=node; with TreeView do begin if IsChecked(CurNode) then // begin sonNode := CurNode.GetFirstChild; //遍历子树,选中 则子节点 全部 为选中; while sonNode<>nil do begin SetChecked(sonNode, true); tvToggleCheckbox(TreeView,sonNode,true); sonNode := sonNode.GetNextSibling; end; ParentNode:= CurNode.Parent; //父; if ParentNode<>nil then begin if not isChecked(parentNode) then begin GrandSonNode := ParentNode.GetFirstChild; //遍历子树; flg1 := false; while GrandSonNode<>nil do begin if (not IsChecked(GrandSonNode)) then //true,有未选中 flg1 := true; if flg1 then //已有、退出loop; GrandSonNode := nil else GrandSonNode := GrandSonNode.GetNextSibling; end; SetChecked(ParentNode, not flg1); tvToggleCheckbox(TreeView,ParentNode,false); end; end; // end parentNode 不等于空 end else if not IsChecked(CurNode) then begin ParentNode := CurNode.Parent; //父; if ParentNode<>nil then begin if isChecked(parentNode) then begin SetChecked(ParentNode, false); tvToggleCheckbox(TreeView,ParentNode); end; end; //end parentnode if (isclick) then begin sonNode := CurNode.GetFirstChild; //遍历子树,未选中 则子节点 全部 为未选中; while sonNode<>nil do begin SetChecked(sonNode, false); tvToggleCheckbox(TreeView,sonNode,true); sonNode := sonNode.GetNextSibling; end; end; end; end; end; procedure TForm1.aaaaa(mMenu: TMenuItem{父节子}; nNode: TTreeNodes{};p_node: TTreeNode{}); var i: Integer; c_node: TTreeNode; begin for i := 0 to mMenu.Count - 1 do begin if mMenu.Items[i].Caption <> '-' then begin c_node := nNode.AddChild(p_node,mMenu.Items[i].Caption); aaaaa(mMenu.Items[i],nNode,c_node); //递归 end; end; end; procedure treeCldnode(Anode: TTreeNode; Query: TADOQuery); var TVI: TTVItem; i: integer; node: TTreeNode; right,sql : string; begin for i := 0 to Anode.Count - 1 do begin Node := ANode.Item[i]; TVI.mask := TVIF_STATE; TVI.hItem := Node.ItemId; TreeView_GetItem(Anode.Handle, TVI); if TVI.state and $2000 = $2000 then right := '1' else right := '0'; //sql := 'update UserRights set Rights='''+Right+''' where UserGroups=''管理员'' and MenuCaptions='''+Anode.Item[i].Text+''''; sql := 'insert into UserRights(UserGroups,MenuCaptions,Rights) values(''' +'收银员'','''+Anode.Item[i].Text+''','''+right+''')'; Query.Close; Query.SQL.Clear; Query.SQL.Add(sql); Query.ExecSQL; if node.Count > 0 then treeCldnode(Node,Query); end; end; procedure TraverseTreeView(Anode1: TTreeNode; Menu: string; Rig: Boolean); var i: integer; node: TTreeNode; sql :string; begin for i := 0 to Anode1.Count - 1 do begin Node := ANode1.Item[i]; if Anode1.Item[i].Text = Menu then begin if Rig then SetChecked(node, True) else SetChecked(node, False); end; if node.Count > 0 then TraverseTreeView(Node,Menu,Rig); end; end; //遍历菜单 procedure TForm1.btn1Click(Sender: TObject); var i: Integer; parent_node : TTreeNode; begin tv1.Items.Clear; for i:= 0 to mm1.Items.Count-1 do //父节子10 begin parent_node := tv1.Items.Add(nil,mm1.Items[i].Caption); aaaaa(mm1.Items[i],tv1.Items, parent_node); end; tv1.FullExpand; end; //加载 procedure TForm1.btn2Click(Sender: TObject); var i,ii: Integer; sql : string; node1 : TTreeNode; rig : Boolean; begin sql := 'select * from UserRights where UserGroups=''管理员'''; qry2.Close; qry2.SQL.Clear; qry2.SQL.Add(sql); qry2.Open; for ii := 0 to qry2.RecordCount do begin MenuCaptions := qry2.FieldByName('MenuCaptions').AsString; Rights := qry2.FieldByName('Rights').AsString; rig := Bool(StrToInt(Rights)); //rig := true; for i := 0 to tv1.Items.Count - 1 do begin node1 := tv1.Items[i]; TraverseTreeView(node1,MenuCaptions,rig); end; qry2.Next; end; end; //保存菜单到文件 procedure TForm1.btn3Click(Sender: TObject); begin if dlgSave1.Execute then tv1.SaveToFile(dlgSave1.FileName); end; procedure TForm1.btn4Click(Sender: TObject); var i: Integer; parent_node : TTreeNode; begin for i:= 0 to mm1.Items.Count-1 do //父节子10 begin mmo1.Lines.Add(mm1.Items[i].Caption); end; end; //遍历Treeview写数据 procedure TForm1.btn5Click(Sender: TObject); var i: integer; node: TTreeNode; begin for i := 0 to tv1.Items.Count - 1 do begin node := tv1.Items[i]; treeCldnode(node,qry1); end; end; procedure TForm1.FormCreate(Sender: TObject); begin //仅仅这一句话就能让treeview 显示复选框 SetWindowLong(TV1.Handle, GWL_STYLE, GetWindowLong(TV1.Handle, GWL_STYLE) or $00000100); end; //Treeview 点击事件 procedure TForm1.tv1Click(Sender: TObject); var P:TPoint; treenode :TTreeNode; begin GetCursorPos(P); P := Tv1.ScreenToClient(P); if (htOnStateIcon in Tv1.GetHitTestInfoAt(P.X,P.Y)) then begin treenode := Tv1.GetNodeAt(P.X,P.Y); tvToggleCheckbox(Tv1,treenode ,true); end; end; end.
实现方法:
procedure TForm1.btnLoadMenuClick(Sender: TObject); var Rec, I, II : Integer; sql, MenuCaption : string; UserRight : Boolean; label GoToStr; begin sql := 'select * from UserRights where UserGroups='''+DeptName+''''; qrySet.Close; qrySet.SQL.Clear; qrySet.SQL.Add(sql); qrySet.Open; if qryset.RecordCount > 0 then for Rec := 0 to qrySet.RecordCount - 1 do begin MenuCaption := qrySet.FieldByName('MenuCaptions').AsString; //菜单名 UserRight := StrToBool(qrySet.FieldByName('Rights').asString); //1为真; 0为假 for I := 0 to mm1.Items.Count-1 do //遍历菜单 begin for II := 0 to mm1.Items[I].Count - 1 do begin if MenuCaption = mm1.Items[I][II].Caption then begin mm1.Items[I][II].Enabled := UserRight; goto GoToStr; end; end; end; GoToStr : qrySet.Next; end; end;