Delphi 编写菜单权限设置的一个方法《LceMeaning》

以下本人在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;