c#WinForm下窗体权限设计(遍历菜单下的所有菜单及所有form、form中的控件)
一、 描述 管理员通过控制窗体中的某个控件的Enable和visable来达到应用程序的权限控制 二、 设计思路 (一) 读取控件 将menustrip菜单选项绑定到treeview中,根据菜单选项的名称跟窗体名称相等,去 遍历出窗体中的所有form、tabctrol、button、toolstripbutton、等, 结果如下
将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 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/liruiba/archive/2008/08/04/2767432.aspx |