WinForm下窗体权限设计


 

一、   描述

管理员通过控制窗体中的某个控件的Enablevisable来达到应用程序的权限控制

二、   设计思路

(一) 读取控件

menustrip菜单选项绑定到treeview中,根据菜单选项的名称跟窗体名称相等,去

遍历出窗体中的所有formtabctrolbuttontoolstripbutton、等,

结果如下

 

(二) 保存控件

treeview中显示 的控件id跟控件名称一起存入数据库,同时设置控件的可用状态,默认都可用。

(三) 将权限应用到具体窗体中

 

 

三、   数据库的设计

 

四、   关键部位的实现

1)      读取控件的难点

怎么样遍历到应用程序的所有窗体,这里使用了net的反射()

具体方法如下

1)         TraverseForm(string Str)

        public bool TraverseForm(string Str)

        {

            Assembly a = Assembly.LoadFile(Application.ExecutablePath);//.net中的反射

 

            Type[] types = a.GetTypes();

            foreach (Type t in types)

            {

 

                if (t.BaseType.Name == "Form" || t.BaseType.Name == "F_HKXT")

                {

                    Form f = (Form)Activator.CreateInstance(t, true);

 

                    if (f != null)

                    {

                        // MessageBox.Show(f.Text);

                        if (f.Text == Str)

                        {

 

                            return true;

                        }

 

                    }

                }

 

 

            }

            return false;

        }

 

上面这个方法是进行判断窗体的存在性,下面这个方法是将窗体显示到树中

2)   TraverseMenu(Control ctrl)

        #region//遍历MenuStrip所有子菜单并显示到树上,同时判断每个子菜单下是否有子窗体,是调用TraverseFormBDTree方法将其窗体及其控件名显示到treeview中

        /// <summary>

        /// 遍历MenuStrip所有子菜单并显示到树上,同时判断每个子菜单下是否有子窗体,是调用TraverseFormBDTree方法将其窗体及其控件名显示到treeview中

        /// </summary>

        /// <param name="ctrl">是带有Menustrip的一个Form窗体</param>

        public void TraverseMenu(Control ctrl)

        {

            foreach (Control c in ctrl.Controls)//遍历窗体中的控件

            {

                //toolbar1(c);

                if (c is MenuStrip)//判断控件是否为Menustrip

                {

 




 

                    MenuStrip menu = (MenuStrip)c;

 

                    foreach (ToolStripMenuItem MenuItem2 in menu.Items)//遍历menustrip的一级菜单并将其显示到树上

                    {




 

                        treeView1.Nodes.Add(MenuItem2.Name, MenuItem2.Text);

                        treeView1.Nodes[MenuItem2.Name].ToolTipText = "主菜单";

 

                        if (TraverseForm(MenuItem2.Text.Trim()) == true)//调用方法TraverseForm判断是否存在窗体

                        {

                            TraverseFormBDTree(MenuItem2.Text, treeView1.Nodes[MenuItem2.Name]);//存在调用方法TraverseFormBDTree

 

                        }

                        else

                        {

                            for (int i = 0; i < MenuItem2.DropDownItems.Count; i++)//遍历menustrip遍历二级菜单

                            {

                                treeView1.Nodes[MenuItem2.Name].Nodes.Add(MenuItem2.DropDownItems[i].Name, MenuItem2.DropDownItems[i].Text);

                                treeView1.Nodes[MenuItem2.Name].Nodes[MenuItem2.DropDownItems[i].Name].ToolTipText = "一级子菜单";

                                if(TraverseForm(MenuItem2.DropDownItems[i].Text) == true)

                                {

                                    TraverseFormBDTree(MenuItem2.DropDownItems[i].Text, treeView1.Nodes[MenuItem2.Name].Nodes[MenuItem2.DropDownItems[i].Name]);

                                }

                            }

                        }

 

                    }

 

 

                }

 

            }

        }

 

        #endregion

 

上面方法调用了下面这个方法

3)   TraverseFormBDTree(string Str, TreeNode treenode)

 

     #region//获取当前应用程序所有的form窗体并传入菜单中的菜单显示值做为判断条件,如果传入的值可以找到相应窗体,则调用方法遍历此窗体中的所控件

        /// <summary>

        /// //获取当前应用程序所有的form窗体并传入菜单中的菜单显示值做为判断条件,如果传入的值可以找到相应窗体,则调用方法遍历此窗体中的所控件

        /// </summary>

        /// <param name="Str">这里为菜单菜单的显示值</param>

        /// <param name="treenode">树的节点</param>

        public void TraverseFormBDTree(string Str, TreeNode treenode)

使用这个方法后会继续调用 方法 private void TraverseFormCtrlAndBindTree(Control ctrl, TreeNode treenode)将控件名与id也绑定到树中

 

4)   private void TraverseFormCtrlAndBindTree(Control ctrl, TreeNode treenode)

 

 

   #region//递归遍历一个Form中的控件是否为button,或者是toopstrip中的toolstripbutton,如果是将基显示到树上,

        /// <summary>

        /// 递归遍历一个Form中的控件是否为button,或者是toopstrip中的toolstripbutton,如果是将基显示到树上,

        /// </summary>

        /// <param name="ctrl">窗体的控件</param>

        /// <param name="treenode">一个treeview的结点</param>

        private void TraverseFormCtrlAndBindTree(Control ctrl, TreeNode treenode)

 

下面是调用方法将其存入数据库

5)   TraverseTreeAndRead(TreeNodeCollection treenode)

 

        #region//此方法遍历树并切将其内容写到sql语句里

        /// <summary>

        /// 此方法遍历树并切将其内容写到sql语句里

        /// </summary>

        /// <param name="treenode">传入的一组TreeNodeCollection类型的树节点</param>

        private void TraverseTreeAndRead(TreeNodeCollection treenode)

        {

 

            foreach (TreeNode TN in treenode)//遍历窗体中的控件

            {

                switch (TN.ToolTipText)

                {

                    case "主菜单":

                        Code.SetControl.P_Str_MainMenuText = "主菜单" + "^" + TN.Text;

                        Code.SetControl.P_Str_Sub1MenuText = "Sub1Menu";

                        Code.SetControl.P_Str_Sub2MenuText = "Sub2Menu";

                        Code.SetControl.P_Str_Sub3MenuText = "Sub3Menu";

                        Code.SetControl.P_Str_Sub4MenuText = "Sub4Menu";

                        Code.SetControl.P_Str_Sub5MenuText = "Sub5Menu";

                        Code.SetControl.P_Str_BtnText = "P_Str_BtnText";

                        Code.SetControl.P_Str_TSBtnText = "P_Str_TSBtnText";

                        Code.SetControl.P_Str_TP1Text = "P_Str_TP1Text";

                        Code.SetControl.P_Str_TP2Text = "P_Str_TP2Text";

                        Code.SetControl.P_Str_TP1PageText = "P_Str_TP1PageText";

                        Code.SetControl.P_Str_TP2PageText = "P_Str_TP2PageText ";

 

                        sqlStr = "insert into d_privi_lib (login_code,app_name,main_menu,sub1_menu,sub2_menu,sub3_menu,sub4_menu,window_name,tab_name,tabpage_name,tab_name2,tabpage_name2,click_name,use_flag,p_order) " +

                               "values('" + Code.InitData.UserLogin.USER_CODE +"','" + Code.SetControl.P_Str_AppName + "','" + Code.SetControl.P_Str_MainMenuText + "','" + Code.SetControl.P_Str_Sub1MenuText + "','" + Code.SetControl.P_Str_Sub2MenuText + "','" + Code.SetControl.P_Str_Sub3MenuText + "','" + Code.SetControl.P_Str_Sub4MenuText + "','c_hkxt','" + Code.SetControl.P_Str_TP1Text + "','" + Code.SetControl.P_Str_TP1PageText + "','" + Code.SetControl.P_Str_TP2Text + "','" + Code.SetControl.P_Str_TSBtnText + "','" + Code.SetControl.P_Str_BtnText + "','T','123456')";

                        sqlStrArr[i] = EStr.EncryptString(sqlStr, Code.InitData.DESKey);

                        i++;

                        TraverseTreeAndRead(TN.Nodes);

                    default:

                        Code.SetControl.P_Str_TSBtnText = "怎么会多出这个呀!" + i.ToString();

                        sqlStr = "insert into d_privi_lib (login_code,app_name,main_menu,sub1_menu,sub2_menu,sub3_menu,sub4_menu,window_name,tab_name,tabpage_name,tab_name2,tabpage_name2,click_name,use_flag,p_order) " +

                               "values('" + Code.InitData.UserLogin.USER_CODE +"','" + Code.SetControl.P_Str_AppName + "','" + Code.SetControl.P_Str_MainMenuText + "','" + Code.SetControl.P_Str_Sub1MenuText + "','" + Code.SetControl.P_Str_Sub2MenuText + "','" + Code.SetControl.P_Str_Sub3MenuText + "','" + Code.SetControl.P_Str_Sub4MenuText + "','c_hkxt','" + Code.SetControl.P_Str_TP1Text + "','" + Code.SetControl.P_Str_TP1PageText + "','" + Code.SetControl.P_Str_TP2Text + "','" + Code.SetControl.P_Str_TSBtnText + "','" + Code.SetControl.P_Str_BtnText + "','T','123456')";

                        sqlStrArr[i] = EStr.EncryptString(sqlStr, Code.InitData.DESKey);

                        i++;

                        TraverseTreeAndRead(TN.Nodes);

                        break;

 

                }

 

 

 

            }

 

        }

 

        #endregion

1)      控件应用到窗体

这里的思路是设置当个窗体内的控件,这里应用程序所有的窗体都要继承一个父窗体,在父窗体中写方法ReturnCtrlInfo(Control ctrl)、SetButtonEnable(Control ctrl, string[,] StrArr)

最后都在load事件中调用如下    ReturnCtrlInfo(this);

对于包含菜单的页面,这另外在写个方法.

具体方法如下:

1)   ReturnCtrlInfo(Control ctrl)

 

        #region//此方法是从数据库中读取控件名,后调用方法进行窗体控件初始化

        /// <summary>

        /// 此方法是从数据库中读取控件名,后调用方法进行窗体控件初始化

        /// </summary>

        /// <param name="ctrl">控件的名称</param>

 

        public void ReturnCtrlInfo(Control ctrl)

        {

            DataTable DT = new DataTable();

            sqlStr = "select * from d_privi_lib where login_code='liruiba'";

            DS = cser.ReturnDS1(EStr.EncryptString(sqlStr, Code.InitData.DESKey));

            // DS.Tables[0].DefaultView.RowFilter = "SUB1_MENU='toolStripMenuItem4^控件权限设置'";

            DS.Tables[0].DefaultView.RowFilter = "SUB1_MENU ='一级子菜单^" + ctrl.Text + "'";

            DT = DS.Tables[0].DefaultView.ToTable();

            string[,] StrArr = new string[DS.Tables[0].Rows.Count, 2];

            for (int i = 0; i < DT.Rows.Count; i++)

            {

                StrArr[i, 0] = DT.Rows[i]["click_name"].ToString().Split('^').GetValue(0).ToString();//控件名称

                StrArr[i, 1] = DT.Rows[i]["Use_Flag"].ToString();//控件可用标志

                //MessageBox.Show(StrArr[i].ToString());

                // MessageBox.Show(StrArr[i, 0].ToString() + StrArr[i, 1].ToString());

            }

            SetButtonEnable(ctrl, StrArr);

        }

        #endregion

 

 

2)   SetButtonEnable(Control ctrl, string[,] StrArr)

 

#region//遍历控件类型,并与数据库取出的数据比较,后控件控件的可用性

        /// <summary>

        /////遍历控件类型,并与数据库取出的数据比较,后控件控件的可用性

        /// </summary>

        /// <param name="ctrl">控件的名称</param>

        /// <param name="StrArr">在这里代表数据库中取出的控件名称</param>

        void SetButtonEnable(Control ctrl, string[,] StrArr)

        {

            foreach (Control c in ctrl.Controls)//遍历窗体中的控件

            {

            

                if (c is ToolStrip//判断是否为ToolStrip

                {

                    ToolStrip TB = (ToolStrip)c;

 

                    for (int i = 0; i < TB.Items.Count; i++)

                    {

 

                        //MessageBox.Show(TB.Items[i].GetType().ToString());

                        if (TB.Items[i].GetType().ToString() =="System.Windows.Forms.ToolStripButton")//判断是否为ToolStripButton

                        {

                            for (int j = 0; j < StrArr.GetLength(0); j++)

                            {

                                if (StrArr[j, 0] != null)

                                {

                                    // MessageBox.Show(StrArr[i, 0].ToString() + StrArr[i, 1].ToString());

                                    if (TB.Items[i].Name == StrArr[j, 0].ToString())

                                    {

                                        switch (StrArr[j, 1].ToString())

                                        {

 

                                            case "T":

 

                                                ((ToolStripButton)TB.Items[i]).Enabled = true;

                                                break;

                                            case "F":

                                                ((ToolStripButton)TB.Items[i]).Enabled = false;

                                                break;

                                            default:

                                                break;

 

                                        }

                                    }

                                }

 

                            }

                        }

                    }

                }

 

 

                SetButtonEnable(c, StrArr);

            }

        }

        #endregion

五、    

 

版权说明

  如果标题未标有<转载、转>等字则属于作者原创,欢迎转载,其版权归作者和博客园共有。 
  作      者:温景良
  文章出处:http://wenjl520.cnblogs.com/  或  http://www.cnblogs.com/

posted @ 2008-12-10 22:22 温景良(Jason) Views(2345) Comments(4Edit 收藏

  
#1楼 2008-12-19 02:32 | 龙儿  
高手呀,可是希望能有份源码调试一下,能发份吗,Hong.Lin@163.com 谢谢

  
#2楼 2009-07-22 16:17 | 胡秉征  
大侠,源码发给我一份好吗,hubingzheng@gmail.com,谢谢啦!

  
#3楼 2013-05-17 15:47 | di40187  
楼主发一份源码给我吧,最近在学winform权限设置,没有头绪,看你这个好像很不错的样子,谢谢啦!987619310@qq.com

  
#4楼 2014-04-16 09:42 | 罗罗づ  
楼主能给份源码吗? 谢谢。。。 1106703231@qq.com


上一篇:Conda 常用命令行(Linux/Windows 指令通用)


下一篇:Photoshop为美女图片打造出柔美的淡调灰绿色韩系效果