根据权限动态生成菜单栏和工具栏

第一步:配置XML文件MenuItems.xml

           结点如下所示

代码
<?xml version="1.0" encoding="utf-8" ?>
<Menus>  
  
<MenuItem>
    
<Text>内部信息维护</Text>
    
<ItemID>1</ItemID>
    
<ParentItemID>0</ParentItemID>
    
<FormName>frmInnerInfo</FormName>
    
<IsModule>0</IsModule>
    
<Level>1</Level>
    
<ImageName>Text1.ico</ImageName>
  
</MenuItem>
  
<MenuItem>
    
<Text>多媒体信息维护</Text>
    
<ItemID>2</ItemID>
    
<ParentItemID>0</ParentItemID>
    
<FormName></FormName>
    
<IsModule>1</IsModule>
    
<Level>1</Level>
    
<ImageName>Video.ico</ImageName>
  
</MenuItem>
  
<MenuItem>
    
<Text>综合信息维护</Text>
    
<ItemID>3</ItemID>
    
<ParentItemID>0</ParentItemID>
    
<FormName>frmCategory</FormName>
    
<IsModule>0</IsModule>
    
<Level>1</Level>
    
<ImageName>Composite.ico</ImageName>
  
</MenuItem>  
  
<MenuItem>
    
<Text>系统管理</Text>
    
<ItemID>4</ItemID>
    
<ParentItemID>0</ParentItemID>
    
<FormName></FormName>
    
<IsModule>1</IsModule>
    
<Level>1</Level>
    
<ImageName>Video.ico</ImageName>
  
</MenuItem>
  
<MenuItem>
    
<Text>用户管理</Text>
    
<ItemID>1004</ItemID>
    
<ParentItemID>4</ParentItemID>
    
<FormName>frmSystemUsers</FormName>
    
<IsModule>0</IsModule>
    
<Level>1</Level>
    
<ImageName>User.ico</ImageName>
  
</MenuItem>
  
<MenuItem>
    
<Text>角色管理</Text>
    
<ItemID>1005</ItemID>
    
<ParentItemID>4</ParentItemID>
    
<FormName>frmSystemRole</FormName>
    
<IsModule>0</IsModule>
    
<Level>1</Level>
    
<ImageName>Role.ico</ImageName>
  
</MenuItem>
  
<MenuItem>
    
<Text>视频管理</Text>
    
<ItemID>1006</ItemID>
    
<ParentItemID>2</ParentItemID>
    
<FormName>frmSystemRole</FormName>
    
<IsModule>0</IsModule>
    
<Level>2</Level>
    
<ImageName>Video.ico</ImageName>
  
</MenuItem>
  
<MenuItem>
    
<Text>图片管理</Text>
    
<ItemID>1007</ItemID>
    
<ParentItemID>2</ParentItemID>
    
<FormName>frmSystemRole</FormName>
    
<IsModule>0</IsModule>
    
<Level>2</Level>
    
<ImageName>Pic.ico</ImageName>
  
</MenuItem>
  
<MenuItem>
    
<Text>文字消息</Text>
    
<ItemID>1008</ItemID>
    
<ParentItemID>2</ParentItemID>
    
<FormName>frmSystemRole</FormName>
    
<IsModule>0</IsModule>
    
<Level>2</Level>
    
<ImageName>Text.ico</ImageName>
  
</MenuItem>  
</Menus>

其中Text为菜单或工具栏显示内容,ItemID为结点编号,ParentItemID为父结点编号,FormName结点响应的Form名称,IsModule为是否有子结点(1有0没有)Level结点层级,ImageName对应的图标名称

第二步:设置主窗体为MDI窗体

第三步:代码实现,如下,

代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml;
using System.Reflection;
using System.Diagnostics;
using System.Threading;

namespace QueryMachine.BackManager
{
    
public partial class frmMDIMain : Form
    {
        
#region  变量初始化
        
private DataSet ds = new DataSet();
        
string strRoleFilter = "";

        
/// <summary>
        
/// <summary>
        
/// 确认关闭么?
        
/// </summary>
        string resourceClose = "确定要删除么?";

        
/// <summary>
        
/// 确认提示    `       
        
/// </summary>
        string resourceCloseTip = "确认提示";

        
/// <summary>
        
/// 重新登录
        
/// </summary>
        string resourceReLogin = "重新登录";

        
/// <summary>
        
/// 退出系统
        
/// </summary>
        string resourceExit = "退出系统";

        
/// <summary>
        
/// 已经存在运行的实例
        
/// </summary>
        string resourceAlreadyRunning = "已经存在运行的实例!";

        
/// <summary>
        
/// 系统提示
        
/// </summary>
        string resourceSystemTip = "系统提示";

        
#endregion

        
#region 根据提供的XML动态创建菜单项,以及定义菜单项要触发的事件

        
private void CreateToolbar()
        {
            ToolStrip toolStrip 
= new ToolStrip();
            toolStrip.ImageScalingSize 
= new System.Drawing.Size(3232);
           
            DataView dv 
= ds.Tables[0].DefaultView;
            
//通过DataView来过滤数据首先得到最顶层的菜单
            dv.RowFilter = "ParentItemID=0";

            
///根据权限加载响应的菜单
            if (strRoleFilter != "")
            {
                dv.RowFilter 
= "ItemID in (" + strRoleFilter + ")";
            }
            
for (int i = 0; i < dv.Count; i++)
            {
                ToolStripButton tsButton 
= new ToolStripButton();

                
if (Convert.ToInt16(dv[i]["IsModule"]) == 0)
                {
                    tsButton.Text   
= dv[i]["Text"].ToString();
                    tsButton.Name   
= dv[i]["ItemID"].ToString();
                    tsButton.Tag    
= dv[i]["FormName"].ToString();

                    
string strPicPath = "";
                    
if (dv[i]["ImageName"].ToString().Length > 0)
                    {
                        
string path = System.Windows.Forms.Application.StartupPath + @"http://www.cnblogs.com/../";
                        System.IO.Directory.SetCurrentDirectory(path);
                        strPicPath 
= System.IO.Directory.GetCurrentDirectory() + @"\ico\" + dv[i]["ImageName"].ToString();
                        
                        
if (File.Exists(strPicPath))
                        {
                            tsButton.Image 
= Image.FromFile(strPicPath);
                        }
                    }

                    
                    
                    tsButton.ToolTipText 
= dv[i]["Text"].ToString();
                    tsButton.Click 
+= new EventHandler(tsButton_Click);

                    toolStrip.Items.Add(tsButton);
                }
                
else
                {
                    
///tsButton.Tag = dv[i]["FormName"].ToString();
                    //tsButton.Click += new EventHandler(subMenu_Click);
                    
//以ref的方式将顶层菜单传递参数,因为他可以在赋值后再回传。--也许还有更好的方法^_^.
                    CreateSubTsb(Convert.ToInt32(dv[i]["ItemID"]), ds.Tables[0], toolStrip);

                }
                

            }

            
this.Controls.Add(toolStrip);


        }

        
void tsButton_Click(object sender, EventArgs e)
        {
            
//tag属性在这里有用到。
            ///ToolStripItem
            string formName = ((ToolStripItem)sender).Tag.ToString();
            CreateFormInstance(formName, Convert.ToInt32(((ToolStripItem)sender).Name));
        }

        
private void CreateSubTsb(int ItemID, DataTable dt, ToolStrip toolStrip)
        {
            DataView dv 
= new DataView(dt);
            
//过滤出当前父菜单下在所有子菜单数据(仅为下一层的)
            dv.RowFilter = "ParentItemID=" + ItemID.ToString();

            
for (int i = 0; i < dv.Count; i++)
            {
                
                
/***********************************************************************/

                ToolStripButton tsButton 
= new ToolStripButton();

                
if (Convert.ToInt16(dv[i]["IsModule"]) == 0)
                {
                    tsButton.Text 
= dv[i]["Text"].ToString();
                    tsButton.Name 
= dv[i]["ItemID"].ToString();
                    tsButton.Tag 
= dv[i]["FormName"].ToString();
                    
string strPicPath = "";
                    
if (dv[i]["ImageName"].ToString().Length > 0)
                    {
                        
string path = System.Windows.Forms.Application.StartupPath + @"http://www.cnblogs.com/../";
                        System.IO.Directory.SetCurrentDirectory(path);
                        strPicPath 
= System.IO.Directory.GetCurrentDirectory() + @"\ico\" + dv[i]["ImageName"].ToString();

                        
if (File.Exists(strPicPath))
                        {
                            tsButton.Image 
= Image.FromFile(strPicPath);
                        }
                    }
                    
                    tsButton.ToolTipText 
= dv[i]["Text"].ToString();
                    tsButton.Click 
+= new EventHandler(tsButton_Click);
                    toolStrip.Items.Add(tsButton);
                }
                
else
                {
                    
///tsButton.Tag = dv[i]["FormName"].ToString();
                    //tsButton.Click += new EventHandler(subMenu_Click);
                    
//以ref的方式将顶层菜单传递参数,因为他可以在赋值后再回传。--也许还有更好的方法^_^.
                    CreateSubTsb(Convert.ToInt32(dv[i]["ItemID"]), dt, toolStrip);

                }
                
            }
        }       

        
#endregion

        
#region 动态创建菜单
        
private void CreateMenu()
        {        
 
            
//定义一个主菜单
            MenuStrip mainMenu = new MenuStrip();       

            DataView dv 
= ds.Tables[0].DefaultView;
            
//通过DataView来过滤数据首先得到最顶层的菜单
            dv.RowFilter = "ParentItemID=0";

            
///根据权限加载相应的菜单
            
            
if (strRoleFilter!="")
            {
                dv.RowFilter 
= "ItemID in (" + strRoleFilter + ")";
            }
            
            
for (int i = 0; i < dv.Count; i++)
            {
                
//创建一个菜单项
                ToolStripMenuItem topMenu = new ToolStripMenuItem();

                
//给菜单赋Text值。也就是在界面上看到的值。

                topMenu.Text 
= dv[i]["Text"].ToString();
                topMenu.Name 
= dv[i]["ItemID"].ToString();


                
//如果是有下级菜单则通过CreateSubMenu方法来创建下级菜单
                if (Convert.ToInt16(dv[i]["IsModule"]) == 1)
                {
                    
//以ref的方式将顶层菜单传递参数,因为他可以在赋值后再回传。--也许还有更好的方法^_^.
                    CreateSubMenu(ref topMenu, Convert.ToInt32(dv[i]["ItemID"]), ds.Tables[0]);
                }
                
else 
                {
                    topMenu.Tag 
= dv[i]["FormName"].ToString();
                    topMenu.Click 
+= new EventHandler(subMenu_Click);
                }

                
//显示应用程序中已打开的 MDI 子窗体列表的菜单项
                mainMenu.MdiWindowListItem = topMenu;
                
//将递归附加好的菜单加到菜单根项上。
                mainMenu.Items.Add(topMenu);
            }

            ToolStripMenuItem exitMenu 
= new ToolStripMenuItem();
            mainMenu.Dock 
= DockStyle.Top;

            mainMenu.Items.Add(
new ToolStripMenuItem(resourceReLogin, nullnew EventHandler(ReLogin_Click)));
            mainMenu.Items.Add(
new ToolStripMenuItem(resourceExit, nullnew EventHandler(ExitSysMenu_Click)));
            
//这句很重要。如果不写这句菜单将不会出现在主窗体中。
            this.Controls.Add(mainMenu); 

        }

        
/// <summary>
        
/// 创建子菜单
        
/// </summary>
        
/// <param name="topMenu">父菜单项</param>
        
/// <param name="ItemID">父菜单的ID</param>
        
/// <param name="dt">所有菜单数据集</param>
        private void CreateSubMenu(ref ToolStripMenuItem topMenu, int ItemID, DataTable dt)
        {
            DataView dv 
= new DataView(dt);
            
//过滤出当前父菜单下在所有子菜单数据(仅为下一层的)
            dv.RowFilter = "ParentItemID=" + ItemID.ToString();

            
for (int i = 0; i < dv.Count; i++)
            {
                
//创建子菜单项
                ToolStripMenuItem subMenu = new ToolStripMenuItem();
                subMenu.Text 
= dv[i]["Text"].ToString();
                subMenu.Name 
= dv[i]["ItemID"].ToString();
                
//如果还有子菜单则继续递归加载。
                if (Convert.ToInt16(dv[i]["IsModule"]) == 1)
                {
                    
//递归调用
                    CreateSubMenu(ref subMenu, Convert.ToInt32(dv[i]["ItemID"]), dt);
                }
                
else
                {
                    
//扩展属性可以加任何想要的值。这里用formName属性来加载窗体。
                    subMenu.Tag = dv[i]["FormName"].ToString();
                    
//给没有子菜单的菜单项加事件。
                    ///subMenu.Click += new EventHandler(subMenu_Click);
                    subMenu.Click += new EventHandler(subMenu_Click);
                }
                
string strPicPath = "";
                
if (dv[i]["ImageName"].ToString().Length > 0)
                {
                    
string path = System.Windows.Forms.Application.StartupPath + @"http://www.cnblogs.com/../";
                    System.IO.Directory.SetCurrentDirectory(path);
                    strPicPath 
= System.IO.Directory.GetCurrentDirectory() + @"\ico\" + dv[i]["ImageName"].ToString();

                    
if (File.Exists(strPicPath))
                    {
                        
//设置菜单项前面的图票为16X16的图片文件。
                        Image img = Image.FromFile(strPicPath);
                        subMenu.Image 
= img;
                        subMenu.Image.Tag 
= dv[i]["ImageName"].ToString();
                    }
                }

                
//将菜单加到顶层菜单下。
                topMenu.DropDownItems.Add(subMenu);
            }
        }

        
void subMenu_Click(object sender, EventArgs e)
        {
            
//tag属性在这里有用到。
            string formName = ((ToolStripMenuItem)sender).Tag.ToString();
            CreateFormInstance(formName, Convert.ToInt32(((ToolStripMenuItem)sender).Name));

        }
        
private void CreateFormInstance(string formName, int id)
        {
            
bool flag = false;
            
//遍历主窗口上的所有子菜单
            for (int i = 0; i < this.MdiChildren.Length; i++)
            {
                
//如果所点的窗口被打开则重新激活
                if (this.MdiChildren[i].Tag.ToString().ToLower() == formName.ToLower())
                {
                    
this.MdiChildren[i].Activate();
                    
this.MdiChildren[i].Show();
                    
this.MdiChildren[i].WindowState = FormWindowState.Normal;
                    flag 
= true;
                    
break;
                }
            }
            
if (!flag)
            {
                
//如果不存在则用反射创建form窗体实例。
                object frmObj = null;
                
                frmObj 
= Activator.CreateInstance(Type.GetType("QueryMachine.BackManager." + formName));

                
// object frmObj = asm.CreateInstance("Kimbanx.SecurityDiskSystem.FactoryTools." + formName);//程序集+form的类名。
                Form frms = (Form)frmObj;
                
//tag属性要重新写一次,否则在第二次的时候取不到。原因还不清楚。有知道的望告知。
                frms.Tag = formName.ToString();
                frms.MdiParent 
= this;
                frms.Show();
            }
        }
        
#endregion

        
#region 窗体关闭事件,窗体加载事件,窗体构造函数
        

        
public frmMDIMain()
        {
            InitializeComponent();
            ds.ReadXml(System.AppDomain.CurrentDomain.BaseDirectory.ToString() 
+ "MenuItems.xml");

            
for (int i = 0; i < UserInfo.lstModule.Count; i++)
            {
                strRoleFilter 
+= (strRoleFilter == "" ? UserInfo.lstModule[i].ToString() : ("," + UserInfo.lstModule[i].ToString()));
            }
        }

        
private void frmMDIMain_Load(object sender, EventArgs e)
        {
            CreateToolbar();
            CreateMenu();
        }

        
private void ExitSysMenu_Click(object sender, EventArgs e)
        {
            
this.Close();
            
        }

        
private void ReLogin_Click(object sender, EventArgs e)
        {
            
            Process process 
= new Process();
            process.StartInfo.FileName 
= System.AppDomain.CurrentDomain.BaseDirectory.ToString()+"QueryMachine.exe";
            process.Start();
            Application.Exit();
            
bool flag = false;
            Mutex mutex 
= new Mutex(true"QueryMachine.BackManager.frmLogin"out flag);
            
if (flag)
            {
                frmLogin Login 
= new frmLogin();
                
                
if (Login.ShowDialog() == DialogResult.OK)
                {
                    Application.Run(
new frmMDIMain());
                }
            }
            
else
            {
                MessageBox.Show(resourceAlreadyRunning,resourceSystemTip, MessageBoxButtons.OK, MessageBoxIcon.Information);
                Application.Exit();
            }
        }

        
#endregion     

        
private void frmMDIMain_FormClosing(object sender, FormClosingEventArgs e)
        {

            
if (e.CloseReason != CloseReason.ApplicationExitCall)
            {
                DialogResult re 
= MessageBox.Show(resourceClose,resourceCloseTip, MessageBoxButtons.YesNo, MessageBoxIcon.Information);
                
if (re == DialogResult.Yes)
                {
                    e.Cancel 
= false;

                    Application.Exit();
                }
                
else
                {
                    e.Cancel 
= true;
                }
            } 

        }

    }
}
原文地址:https://www.cnblogs.com/pato/p/1690459.html