***菜单权限控制:源码奉送***  V1.0请参见:http://expert.csdn.net/Expert/topic/917/917914.xml?temp=.2989771代码版本现已升级 V2.0,公布源代码--------------------------------------------------------------------------
*****菜单权限分配源码奉送V2.0*****针对以前版本功能有所扩展,增加了模块单元的操作控制//使用ActionMainMenuBar、ActionManager、ActionToolBar效果更佳
//也可以MainMenu、ToolBar、ActionList的组合
数据库表:CREATE TABLE [操作员] (
[操作员ID] [varchar] (15) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[姓名] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[口令] [varchar] (15) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[级别] [tinyint] NOT NULL CONSTRAINT [DF_操作员_级别] DEFAULT (2),
[部门ID] [varchar] (10) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[标志] [bit] NOT NULL CONSTRAINT [DF_操作员_标志] DEFAULT (0),
CONSTRAINT [PK_操作员] PRIMARY KEY  CLUSTERED 
(
[操作员ID]
)  ON [PRIMARY] 
) ON [PRIMARY]
GO
CREATE TABLE [操作员权限] (
[操作员ID] [char] (15) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[功能ID] [varchar] (30) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[Visible] [bit] NOT NULL CONSTRAINT [DF_操作员权限_Visible] DEFAULT (0),
[Enabled] [bit] NOT NULL CONSTRAINT [DF_操作员权限_Enabled] DEFAULT (0),
[权限组ID] [char] (2) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[操作标识] [char] (6) COLLATE Chinese_PRC_CI_AS NOT NULL ,
CONSTRAINT [PK_操作员权限] PRIMARY KEY  CLUSTERED 
(
[操作员ID],
[功能ID]
)  ON [PRIMARY] 
) ON [PRIMARY]
GO
CREATE TABLE [权限组] (
[权限组ID] [char] (2) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[权限组名称] [varchar] (20) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[标志] [tinyint] NOT NULL CONSTRAINT [DF_权限组_标志] DEFAULT (0),
CONSTRAINT [PK_权限组] PRIMARY KEY  CLUSTERED 
(
[权限组ID]
)  ON [PRIMARY] 
) ON [PRIMARY]
GO
CREATE TABLE [权限组功能分配] (
[权限组ID] [char] (2) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[功能ID] [varchar] (30) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[操作标识] [char] (6) COLLATE Chinese_PRC_CI_AS NOT NULL ,
CONSTRAINT [PK_权限组功能分配] PRIMARY KEY  CLUSTERED 
(
[权限组ID],
[功能ID]
)  ON [PRIMARY] 
) ON [PRIMARY]
GO
CREATE TABLE [系统功能] (
[功能ID] [varchar] (30) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[菜单名] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[说明] [varchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[分类] [varchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[操作标识] [char] (6) COLLATE Chinese_PRC_CI_AS NOT NULL ,
CONSTRAINT [PK_系统功能] PRIMARY KEY  CLUSTERED 
(
[功能ID]
)  ON [PRIMARY] 
) ON [PRIMARY]
GO--“分类”字段的类型改为varchar(50)//原版本为bit--增加了“操作标识”字段:由6位数字组成,
  约定:第一位:无意义,以1表示,
        第二位:增加,以1或0表示,
        第三位:修改,以1或0表示,
        第四位:删除,以1或0表示,
        第五位:查询,以1或0表示,
        第六位:打印,以1或0表示操作标识有两层含义:1、系统功能的“操作标识”,2、操作员的的“操作标识”操作员的的“操作标识”,例如:字符串‘110010’表示可以增加和查询,不能修改、删除和打印系统功能的“操作标识”:必须在设计期间定义Action的操作标识,表示有没有该项功能例如:字符串‘100011’表示该模块有查询、打印功能,没有增加、修改、删除
有效利用Action的各项属性:Name: 功能ID
Caption:菜单名
Hint:说明
Category:分类
Tag:操作标识
定义全局变量:var
  ActName,OperaID:TStringList; //功能ID列表,操作标识列表。变量创建过程,这里省略
  CurrentOperaID:String;       //当前操作标识 
//权限分配方法
procedure TMainFrm.AssignLimit;
var
  i, j, k, TlbLen: integer;
  Ks, Ms: Boolean;
begin  for i := 0 to ActionList1.ActionCount - 1 do //所有功能不可用
  begin
    TAction(ActionList1.Actions[i]).Visible := False;
    TAction(ActionList1.Actions[i]).Enabled := False;
  end;  ActName.Clear;  //清除功能ID列表
  OperaID.Clear;  //清除操作标识列表  for i := 0 to ActionList1.ActionCount - 1 do //分配权限
  begin
    if LoginFrm.CDSLimit.Locate('功能ID', TAction(ActionList1.Actions[i]).Name, [loPartialKey]) then
    begin
      TAction(ActionList1.Actions[i]).Enabled := LoginFrm.CDSLimit.FieldByName('Enabled').AsBoolean;
      TAction(ActionList1.Actions[i]).Visible := LoginFrm.CDSLimit.FieldByName('Visible').AsBoolean;
      
      ActName.Add(TAction(ActionList1.Actions[i]).Name);//加入功能ID
      OperaID.Add(LoginFrm.CDSLimit.FieldByName('操作标识').AsString);//加入操作标识
    end;
  end;//----------------------------菜单效果------------------------------------------  if LoginFrm.Grade = '0' then //超级管理员固定权限
  begin
    mmMenuInit.Visible := True; //功能初始化
    mmPopGroup.Visible := True; //权限组功能分配
    ActOperAssign.Visible := True; //操作员权限分配
    ActOperAssign.Enabled := True;
    ActSysLogQry.Visible := True; //操作员权限分配
    ActSysLogQry.Enabled := True;
  end else
  begin
    mmMenuInit.Visible := false;
    mmPopGroup.Visible := false;
  end;  Ks := False;
  Ms := False;  for I := 0 to MainMenu.Items.Count - 1 do //一级菜单
  begin
    for J := 0 to MainMenu.items[I].count - 1 do //二级菜单
    begin
      if MainMenu.items[I].Items[J].Count > 0 then //若存在三级菜单
      begin
        for K := 0 to MainMenu.items[I].Items[J].Count - 1 do //三级菜单
        begin
          if (MainMenu.items[I].Items[J].Items[K].Visible) and
            (MainMenu.items[I].Items[J].Items[K].Caption <> '-') then
          begin
            Ks := True;
            Break; //在三级菜单中若存在Visible为True则跳出循环
          end;
        end;
        MainMenu.items[I].Items[J].Visible := Ks;
        if Ks then Ms := True;
        Ks := False;
      end else
        if (MainMenu.items[I].Items[J].Visible) and
          (MainMenu.items[I].Items[J].Caption <> '-') then
        begin
          Ms := True; //在二级菜单中若存在Visible为True则主菜单可见
        end;
    end;
    MainMenu.items[I].Visible := Ms;
    Ms := False;
  end;//-------------------------------快捷菜单效果-----------------------------------  TlbLen := 0;
  j:=0;
  k:=0;
  for i := 0 to ToolBar1.ButtonCount - 1 do
  begin
    if ToolBar1.Buttons[i].Visible then
    begin
      if (j=0)and(ToolBar1.Buttons[i].Style=tbsSeparator) then
        ToolBar1.Buttons[i].Visible:=false        //屏蔽分割快捷按钮             
      else
      begin
        if ToolBar1.Buttons[i].Style=tbsSeparator then inc(k);
        if k=2 then        //如果连续排列两个分割快捷按钮
        begin
          ToolBar1.Buttons[i].Visible:=false;   //屏蔽分割快捷按钮
          k:=1;
        end else
        begin
          TlbLen:=TlbLen+ToolBar1.Buttons[i].Width;
          inc(j);
        end;
      end;
    end;
  end;
  CoolBar1.Bands[0].Width := TlbLen + 15;//15这个值是个校正值,可能不适合你
//
end;在每个Action的执行代码中,额外加入以下代码procedure TMainFrm.ActWareBuyPlanExecute(Sender: TObject);
begin
 CurrentOperaID:=OperaID[ActName.IndexOf(TAction(Sender).Name)];//取得当前操作员当前模块的操作标识
 ....
end;全局函数://解析操作标识
function ParseOperaID(const AoperaID:string;index:integer):Boolean;
var
  TmpPos:integer;
begin
  TmpPos:=Index+1;
  if Index<1 then TmpPos:=2;  //把Index固定在1..5之间
  if Index>5 then TmpPos:=6;
  Result:=Copy(AoperaID,TmpPos,1)=1;
end;使用方法例如:BtnAdd.Enable:=ParseOperaID(CurrentOperaID,1);//增加
BtnModi.Enable:=ParseOperaID(CurrentOperaID,2);//修改
BtnDel.Enable:=ParseOperaID(CurrentOperaID,3);//删除建议使用按钮的Tag属性-------------------------------------------------------------------------------------------------与之相关的功能列表:1、系统功能初始化:2、权限组功能分配:3、操作员功能分配:限于篇幅,源代码不再贴出,都是简单的数据库操作。注意一点:  操作标识的显示问题,//总不能把‘100110’显示出来吧
最后一段代码:
在数据集字段的OnGetText事件中:var
  Str:string;
begin
  if ParseO

解决方案 »

  1.   

    能不能MAIL一份源码给我,谢谢!!!
    [email protected]
      

  2.   

    我昨天就看了你的1。0版了,我也想希望你能将源码EMAIL一份我们看看你的窗体的具体实现
    谢谢了!
    [email protected]
      

  3.   

    源码能给我一份吗?[email protected]
    万分感谢!!
      

  4.   

    请求源码者注意:    这套方法用在了一个大型项目上,我不能把这部分源代码完全公布(职业道德,见谅),不过如果有时间我可以做个Demo(附源码)!请多多谅解!
      

  5.   

    理解!!!等待!!!
    [email protected]
      

  6.   

    你简单是人民的好儿了,人民永远感谢你!
    [email protected]
      

  7.   

    to thinkcat(思想猫) :   谢谢,理解万岁!!!----------------------------------------------------------------------------------
    发布源码的主要目的是为了识别其中的缺陷,以及寻求更好的解决方案!
      

  8.   

    好像漏了一段代码(最后没有显示完全):在数据集字段的OnGetText事件中:var
      Str:string;
    begin
      if ParseOperaID(Sender.AsString,1) then Str:='增加';
      if ParseOperaID(Sender.AsString,2) then
        if Str='' then Str:='修改' else Str:=Str+',修改';  ....   Text:=Str;
    end;
      

  9.   

    我原来了做过一个权限控制的程序了应用在一四星级酒店!数据表的设置没什么在的区别,主要是程序上的实现上有很大的区别!希望能互相学习![email protected]
      

  10.   

    to  eggfool(傻蛋) :互相学习 [email protected]如果愿意,不妨写些思路来,让大家参考!
      

  11.   

    Demo
    等待中
    [email protected]
      

  12.   

    能不能E-MAIL一份源码给我,谢谢!!!
    [email protected]
    另外我想看看你的窗体以及控件的配置,谢谢。
      

  13.   

    如果要作成通用的话.我认为你这个还应该要加上一个菜单结构的调功能.
    用户可以根据自已喜欢的方式组织自己的功能菜单结构,可以增加新的菜单,当然这个新的功能菜单可以由用户指定去调用外部的某个EXE文件.比何计算器等一些小工具,这样用户使用起来会更加方便!
      

  14.   

    我正在学习中,希望能把原码也给我email一份~
    谢谢~~~~~
      

  15.   

    人民感谢你,renzhm (戴尔飞) ,发布代码时,别忘了我阿
      E:[email protected]
      

  16.   

    顶之!给我一份!多谢[email protected]
      

  17.   

    给我一份源码吧[email protected]
      

  18.   

    棒极了
    我也要一份
    [email protected]
      

  19.   

    need the Demo.
    [email protected]
      

  20.   

    source and demo,both I need.
    [email protected]
      

  21.   

    棒极了
    我也要一份
    [email protected]
      

  22.   

    给我一份
    [email protected]
      

  23.   

    to  renzhm(戴尔飞)
    能说明一下:
    操作员权限中的“功能ID”和系統功能中的“功能ID”各是什么作用吗??
    另其中的“标志”又是什么作用呢?
      

  24.   

    最近一直没有上网:操作员权限中的“功能ID”:当前操作员拥有的功能
    系統功能中的“功能ID”:所有系统的功能操作员中的“标志”:命名不太确切,确切的说应该是状态,“可用/作废”
    权限组中的“标志”:“系统定义/用户定义”,我在程序中规定,系统定义
    的权限组只可以更名,用户定义的权限组可任意操作,系统定义的权限组
    是在初始化时生成的。
      

  25.   

    太好了,我正在写一个软件需要权限规划,麻烦你发个源码~ 谢谢[email protected]
      

  26.   

    to Goldteerfei(卖海豚的女孩) :不知道您指的动态菜单是什么?我觉得动态创建菜单没有必要
      

  27.   

    楼主的设计方法很好,这类问题我也碰过,可不是什么清楚,能否发个Email给我:[email protected]
    谢谢
      

  28.   

    能否发个Email给我: [email protected]
    谢谢!
      

  29.   

    :)  等待[email protected]
      

  30.   

    留email的朋友请注意:近期将推出“菜单权限控制”的组件1.0a,到时请大家帮忙测试!还有,如果能把您的特别要求(期望的功能)列出,本人不胜感激!to xiaoyan21(明月心) :能不能说说您的要求,我也好使之改进?
      

  31.   

    tag最好了,只要设计好菜单项目的tag成为特殊的数字,然后简单判定tag的数值,就可以方便的管理c了
      

  32.   

    谢谢!给我一份!要全点哈[email protected]
      

  33.   

    谢谢,我也要
     
      [email protected]  
      

  34.   

    今天再次看到这个帖子,上次忘留MAIL了
    [email protected]请楼主无比发给我一份,谢谢
      

  35.   

    谢谢, 太谢谢了![email protected]
      

  36.   

    谢谢!给我一份[email protected]
      

  37.   

    方便的话给我一份了...
    [email protected]
      

  38.   


    谢谢
      
       [email protected]
      

  39.   

    To: renzhm (戴尔飞); 可以给我一份吗? [email protected]
    To: 407107() ;我正在做树型菜单的权限控制,你能给些参考或意见吗?
    谢谢
      

  40.   

    我的E-MAIL 是:        [email protected]
    您的1.0a出现的时候一定全力测试。
      

  41.   

    也给我一份,多谢!
    [email protected]