C#实现基于XML配置MenuStrip菜单的方法

作者:北风其凉 时间:2023-03-06 21:48:50 

本文实例讲述了C#实现基于XML配置MenuStrip菜单的方法。分享给大家供大家参考。具体如下:

1.关于本程序的说明

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

程序示例如下:

C#实现基于XML配置MenuStrip菜单的方法

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>

配置规则:

①.所有的内容都在标签<MenuStrip>中
②.每一个<Menu>标签代表了一个横向的菜单项,其中Text属性是显示的文字,ShortKey属性是选择用的快捷键
③.每一个<Item>标签都在<Menu>或<Item>标签下,表示一个菜单项,菜单项里面可以嵌套其他的Item菜单项。
④.<Item>标签的Type属性代表了此像的类型,分为Seperator和MenuItem两类,前者对应ToolStripItem类,后者对应ToolStripSeparator类
⑤.<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"); }
}
}

希望本文所述对大家的C#程序设计有所帮助。

标签:C#,XML,菜单
0
投稿

猜你喜欢

  • C#异步执行任务的方法

    2022-02-27 15:02:41
  • Java线程公平锁和非公平锁的差异讲解

    2022-06-26 09:59:09
  • c# 基于wpf,开发OFD电子文档阅读器

    2023-09-08 00:10:02
  • mybaties plus selectMaps和selectList的区别说明

    2021-07-15 11:18:29
  • Spring中Bean的生命周期使用解析

    2021-09-06 23:06:54
  • C#实现的MD5加密功能与用法示例

    2023-06-11 09:08:21
  • Android基于OpenGL在GLSurfaceView上绘制三角形及使用投影和相机视图方法示例

    2023-06-08 03:59:42
  • 深入理解Java设计模式之状态模式

    2022-07-07 12:49:44
  • Java 批量文件压缩导出并下载到本地示例代码

    2023-04-15 07:29:30
  • java多线程中的异常处理机制简析

    2021-11-18 01:54:39
  • C#实现目录跳转(TreeView和SplitContainer)的示例代码

    2023-07-31 11:07:59
  • 基于SpringBoot生成二维码的几种实现方式

    2022-02-27 16:24:31
  • 使用IDEA将Java/Kotliin工程导出Jar包的正确姿势

    2022-10-18 17:39:34
  • 详解C#中三个关键字params,Ref,out

    2021-09-25 18:54:02
  • Spring createBeanInstance实例化Bean

    2023-06-17 17:26:27
  • java基础之NIO介绍及使用

    2022-06-07 11:30:14
  • SpringDataElasticsearch与SpEL表达式实现ES动态索引

    2021-11-27 01:33:03
  • C# 拷贝数组的几种方法(总结)

    2023-09-14 06:50:17
  • Spring boot使用多线程过程步骤解析

    2023-04-03 04:54:50
  • Kotlin Navigation可视化开发详解

    2022-10-18 10:55:56
  • asp之家 软件编程 m.aspxhome.com