一、 描述
管理员通过控制窗体中的某个控件的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
五、