C#实现用XML配置MenuStrip菜单

1.关于本程序的说明

用XML配置MenuStrip菜单,本程序只是提供一个思路。程序在Load函数中根据XML文件中的设置动态生成一个MenuStrip组件的Items集合。

程序示例如下:

161432_v6fd_1425762.png

2.使用到的XML文档示例

<?xml version="1.0" encoding="gb2312"?>
<!--MenuStrip:mnsMainMenu控件中的各个菜单配置-->
<!--Menu:菜单栏中的各项,Text:显示名称,ShortKey:快捷键-->
<MenuStrip>
  <Menu Text="文件(File)" ShortKey="Alt+F">
    <Item Type="MenuItem" Text="修改窗口颜色">
      <Item Type="MenuItem" Text="红色" ShortKey="Shift+F6"
            FunctionAttribute="ColorToRed" />
      <Item Type="MenuItem" Text="绿色" ShortKey="Shift+F7"
            FunctionAttribute="ColorToLawnGreen" />
    </Item>
    <Item Type="Seperator" />
    <Item Type="MenuItem" Text="普通" ShortKey="Ctrl+Shift+X"
          FunctionAttribute="FormNormal" />
    <Item Type="MenuItem" Text="最小化" ShortKey="Ctrl+Shift+Y" 
          FunctionAttribute="FormMinimize" />
    <Item Type="MenuItem" Text="最大化" ShortKey="Ctrl+Shift+Z" 
          FunctionAttribute="FormMaximize" />
    <Item Type="Seperator" />
    <Item Type="MenuItem" Text="关闭" ShortKey="Alt+F4"
          FunctionAttribute="FormClose" />
  </Menu>
  <Menu Text="帮助(Help)" ShortKey="Alt+F">
    <Item Type="MenuItem" Text="关于" FunctionAttribute="FormAbout" />  
  </Menu>
</MenuStrip>

 

配置规则:

1.所有的内容都在标签<MenuStrip>中

2.每一个<Menu>标签代表了一个横向的菜单项,其中Text属性是显示的文字,ShortKey属性是选择用的快捷键

3.每一个<Item>标签都在<Menu>或<Item>标签下,表示一个菜单项,菜单项里面可以嵌套其他的Item菜单项。

4.<Item>标签的Type属性代表了此像的类型,分为Seperator和MenuItem两类,前者对应ToolStripItem类,后者对应ToolStripSeparator类

5.<Item>标签中,Type属性为MenuItem时,还可以设置Text属性(显示文字)、ShortKey属性(快捷键)、FunctionAttribute属性(生成实例后,单击此菜单项需要调用的函数绑定特性值)

另:在本程序中单击生成后的菜单调用的是一个函数,该函数上方有一个RemarkAttribute特性,FunctionAttribute属性的值如果与之一致则调用该函数。这个特性的设计并不是死的,在本程序中是函数,经过修改后,也可以对应自定义控件、类等。

3.关于程序窗体

程序窗体没有设置其他的属性,只有一个空的MenuStrip,名为mnsMainMenu。窗体的名称为FormMain。

4.程序代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Xml;
using System.Reflection;

namespace Program22
{
    public partial class FormMain : Form
    {
        public FormMain()
        {
            InitializeComponent();
        }

        //1.把MenuConfig.xml中的信息反映到菜单mnsMainMenu上
        //2.显示文本、快捷键等信息直接添加,FunctionName属性添加到Tag中
        //3.通过反射找到对应函数,完成操作

        private void Form1_Load(object sender, EventArgs e)
        {
            SetMainMenu("MenuConfig.xml");
        }

        /// <summary>
        /// 设置MenuStrip控件
        /// </summary>
        /// <param name="address"></param>
        private void SetMainMenu(string address)
        {
            //设置前清空MenuStrip中所有项
            mnsMainMenu.Items.Clear();

            //读取XML文件
            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(address);

            XmlNode root = xmlDoc.SelectSingleNode("MenuStrip");
            SetMenu(mnsMainMenu, root);
        }

        /// <summary>
        /// 设置MenuStrip控件第一层菜单及其子菜单
        /// </summary>
        /// <param name="ms">MenuStrip控件</param>
        /// <param name="xnode">XML结点</param>
        private void SetMenu(MenuStrip ms, XmlNode xnode)
        {
            foreach (XmlNode xn in xnode.ChildNodes)
            {
                XmlElement xe = (XmlElement)xn;
                ToolStripMenuItem newtsmi = new ToolStripMenuItem(xe.GetAttribute("Text"));

                //设置快捷键
                if (string.IsNullOrWhiteSpace(xe.GetAttribute("ShortKey")))
                {
                    SetShortKey(newtsmi, xe.GetAttribute("ShortKey"));
                }

                //设置调用函数
                if (!string.IsNullOrWhiteSpace(xe.GetAttribute("FunctionAttribute")))
                {
                    newtsmi.Tag = xe.GetAttribute("FunctionAttribute");
                    newtsmi.Click += ToolStripMenuItem_Click;
                }

                //设置子菜单
                if (xn.ChildNodes.Count != 0)
                {
                    SetItem(newtsmi, xn);
                }

                ms.Items.Add(newtsmi);
            }
        }

        /// <summary>
        /// 设置 ToolStripMenuItem 控件及其子菜单(递归设置)
        /// </summary>
        /// <param name="tsmi">ToolStripMenuItem控件</param>
        /// <param name="xnode">XML结点</param>
        private void SetItem(ToolStripMenuItem tsmi, XmlNode xnode)
        {
            foreach (XmlNode xn in xnode.ChildNodes)
            {
                XmlElement xe = (XmlElement)xn;
                ToolStripMenuItem newtsmi = new ToolStripMenuItem(xe.GetAttribute("Text"));

                switch (xe.GetAttribute("Type"))
                {
                    case "MenuItem": 
                        {
                            //设置快捷键
                            if (!string.IsNullOrWhiteSpace(xe.GetAttribute("ShortKey")))
                            {
                                SetShortKey(newtsmi, xe.GetAttribute("ShortKey"));
                            }

                            //设置调用函数
                            if (!string.IsNullOrWhiteSpace(
                                xe.GetAttribute("FunctionAttribute")))
                            {
                                newtsmi.Tag = xe.GetAttribute("FunctionAttribute");
                                newtsmi.Click += ToolStripMenuItem_Click;
                            }

                            //设置子菜单
                            if (xn.ChildNodes.Count != 0)
                            {
                                SetItem(newtsmi, xn);
                            }

                            tsmi.DropDownItems.Add(newtsmi as ToolStripItem);
                        } break;
                    case "Seperator":
                        {
                            tsmi.DropDownItems.Add(new ToolStripSeparator());
                        } break;
                    default: break;
                }

            }
        }

        /// <summary>
        /// 通过字符串(如"Ctrl+Alt+A")判断按键信息
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private void SetShortKey(ToolStripMenuItem tsmi, string key)
        {
            System.Windows.Forms.Keys result = default(System.Windows.Forms.Keys);

            string[] keys = key.Split('+');

            if (keys.Contains("Ctrl")) { result |= Keys.Control; }
            if (keys.Contains("Shift")) { result |= Keys.Shift; }
            if (keys.Contains("Alt")) { result |= Keys.Alt; }

            if (keys.Contains("A")) { result |= Keys.A; }
            if (keys.Contains("B")) { result |= Keys.B; }
            if (keys.Contains("C")) { result |= Keys.C; }
            if (keys.Contains("D")) { result |= Keys.D; }
            if (keys.Contains("E")) { result |= Keys.E; }
            if (keys.Contains("F")) { result |= Keys.F; }
            if (keys.Contains("G")) { result |= Keys.G; }

            if (keys.Contains("H")) { result |= Keys.H; }
            if (keys.Contains("I")) { result |= Keys.I; }
            if (keys.Contains("J")) { result |= Keys.J; }
            if (keys.Contains("K")) { result |= Keys.K; }
            if (keys.Contains("L")) { result |= Keys.L; }
            if (keys.Contains("M")) { result |= Keys.M; }
            if (keys.Contains("N")) { result |= Keys.N; }

            if (keys.Contains("O")) { result |= Keys.O; }
            if (keys.Contains("P")) { result |= Keys.P; }
            if (keys.Contains("Q")) { result |= Keys.Q; }
            if (keys.Contains("R")) { result |= Keys.R; }
            if (keys.Contains("S")) { result |= Keys.S; }
            if (keys.Contains("T")) { result |= Keys.T; }

            if (keys.Contains("U")) { result |= Keys.U; }
            if (keys.Contains("V")) { result |= Keys.V; }
            if (keys.Contains("W")) { result |= Keys.W; }
            if (keys.Contains("X")) { result |= Keys.X; }
            if (keys.Contains("Y")) { result |= Keys.Y; }
            if (keys.Contains("Z")) { result |= Keys.Z; }

            if (keys.Contains("0")) { result |= Keys.D0; }
            if (keys.Contains("1")) { result |= Keys.D1; }
            if (keys.Contains("2")) { result |= Keys.D2; }
            if (keys.Contains("3")) { result |= Keys.D3; }
            if (keys.Contains("4")) { result |= Keys.D4; }

            if (keys.Contains("5")) { result |= Keys.D5; }
            if (keys.Contains("6")) { result |= Keys.D6; }
            if (keys.Contains("7")) { result |= Keys.D7; }
            if (keys.Contains("8")) { result |= Keys.D8; }
            if (keys.Contains("9")) { result |= Keys.D9; }

            if (keys.Contains("F1")) { result |= Keys.F1; }
            if (keys.Contains("F2")) { result |= Keys.F2; }
            if (keys.Contains("F3")) { result |= Keys.F3; }
            if (keys.Contains("F4")) { result |= Keys.F4; }
            if (keys.Contains("F5")) { result |= Keys.F5; }
            if (keys.Contains("F6")) { result |= Keys.F6; }

            if (keys.Contains("F7")) { result |= Keys.F7; }
            if (keys.Contains("F8")) { result |= Keys.F8; }
            if (keys.Contains("F9")) { result |= Keys.F9; }
            if (keys.Contains("F10")) { result |= Keys.F10; }
            if (keys.Contains("F11")) { result |= Keys.F11; }
            if (keys.Contains("F12")) { result |= Keys.F12; }

            tsmi.ShortcutKeys = result;
        }

        /// <summary>
        /// 特性 RemarkAttribute,用在函数上,其 Remark 属性决定了
        /// 积分函数 Integration 应该选择程序中的哪个函数进行计算
        /// </summary>
        [AttributeUsage(AttributeTargets.Method)]
        public class RemarkAttribute : Attribute
        {
            string remark;
            public string Remark
            {
                get { return remark; }
            }

            //构造函数
            public RemarkAttribute(string comment)
            {
                remark = comment;
            }
        }

        /// <summary>
        /// 单击一个ToolStripMenuItem后触发的事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //如果Tag为空,则不执行任何事件
            if (string.IsNullOrWhiteSpace((string)((ToolStripMenuItem)sender).Tag))
            {
                return;
            }

            //如果Tag存在,则寻找具有和Tag内容一致特性的函数并调用
            FunctionInvoke((string)((ToolStripMenuItem)sender).Tag);
        }

        /// <summary>
        /// 调用具有指定特性名的函数
        /// </summary>
        /// <param name="funcattr">函数的RemarkAttribute特性值</param>
        private void FunctionInvoke(string funcattr)
        {
            //需要 using System.Reflection;
            MethodInfo[] mi = typeof(FormMain).GetMethods(
                BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            //找到具有指定特性的函数,进行调用
            foreach (MethodInfo m in mi)
            {
                Type t2 = typeof(RemarkAttribute);
                RemarkAttribute ra = (RemarkAttribute)Attribute.GetCustomAttribute(m, t2);
                if (ra != null && ra.Remark == funcattr)
                {
                    m.Invoke(this, new object[] { });
                    break;
                }
            }
        }

        //需要调用的函数
        [RemarkAttribute("ColorToRed")]  //窗口底色:红
        private void ChangeColorToRed() { this.BackColor = Color.Red; }
        [RemarkAttribute("ColorToLawnGreen")]  //窗口底色:绿
        private void ChangeColorToLawnGreen() { this.BackColor = Color.LawnGreen; }

        [RemarkAttribute("FormNormal")]  //窗口大小:普通
        private void ChangeSizeToNrm() { this.WindowState = FormWindowState.Normal; }
        [RemarkAttribute("FormMinimize")]  //窗口大小:最小化
        private void ChangeSizeToMin() { this.WindowState = FormWindowState.Minimized; }
        [RemarkAttribute("FormMaximize")]  //窗口大小:最大化
        private void ChangeSizeToMax() { this.WindowState = FormWindowState.Maximized; }

        [RemarkAttribute("FormClose")]  //退出程序
        private void CloseForm() { Application.Exit(); }
        [RemarkAttribute("FormAbout")]  //关于程序
        private void AboutForm() { MessageBox.Show("Write By Tsybius 2014/5/15"); }
    }
}

END

转载于:https://my.oschina.net/Tsybius2014/blog/265279

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值