动态菜单

在不重新编译主程序的情况下要对程序的功能进行扩充,我们可以使用动态生成菜单,将新增的窗体编译成dll文件,然后在主程序的菜单定义文件中注册,即可解决,以后程序升级,只需将对应的dll覆盖。

1.菜单定义文件可以使用ini或XML格式,这里使用的是XML格式

定义主菜单,子菜单,子菜单对应的dll,子菜单对应的函数

dymenu.xml内容如下

 1<root>   
 2&lt;主菜单&gt;动态菜单1   
 3&lt;子菜单&gt;OpenForm1<!--子菜单-->   
 4&lt;菜单DLL&gt;MyForms.dll<!--菜单DLL-->   
 5&lt;菜单Func&gt;OpenForm1<!--菜单Func-->   
 6&lt;子菜单&gt;OpenForm2<!--子菜单-->   
 7&lt;菜单DLL&gt;MyForms.dll<!--菜单DLL-->   
 8&lt;菜单Func&gt;OpenForm2<!--菜单Func-->
 9<!--主菜单-->   
10&lt;主菜单&gt;动态菜单2   
11&lt;子菜单&gt;OpenForm3<!--子菜单-->   
12&lt;菜单DLL&gt;MyForms.dll<!--菜单DLL-->   
13&lt;菜单Func&gt;OpenForm3<!--菜单Func-->
14<!--主菜单-->   
15&lt;主菜单&gt;动态菜单3   
16&lt;子菜单&gt;OpenForm4<!--子菜单-->   
17&lt;菜单DLL&gt;MyForms.dll<!--菜单DLL-->   
18&lt;菜单Func&gt;OpenForm4<!--菜单Func-->
19<!--主菜单-->
20</root>

2.菜单对应的MyForms.dll

MyForms.cs 代码如下:

using System;

namespace MyForms
{
public class MyForms
{
public MyForms()
{
}
public void OpenForm1(System.Windows.Forms.Form mainf)
{
Form1 fm = new Form1();
fm.MdiParent = mainf;
fm.Show();
}

public void OpenForm2(System.Windows.Forms.Form mainf)
{
Form2 fm = new Form2();
fm.MdiParent = mainf;
fm.Show();
}
public void OpenForm3(System.Windows.Forms.Form mainf)
{
Form3 fm = new Form3();
fm.MdiParent = mainf;
fm.Show();
}

public void OpenForm4(System.Windows.Forms.Form mainf)
{
Form4 fm = new Form4();
fm.MdiParent = mainf;
fm.Show();
}

}
}

另外还有4个窗体Form1 Form2 Form3 Form4

这里使用的namespace 构造函数 都和dll的名字一致,是为了方便后面主程序调用

3.主程序DyMenu.cs

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Reflection;
using System.Xml;

namespace DyMenu
{
///

1<summary>   
2/// Form1 的摘要说明。   
3/// </summary>

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.MainMenu mainMenu1;

//主菜单
private string[] mMenus;
//子菜单
private string[][] mItems;
//子菜单对应的dll
private string[][] mDlls;
//子菜单对应的函数
private string [][] mFuncs;
///

1<summary>   
2/// 必需的设计器变量。   
3/// </summary>

private System.ComponentModel.Container components = null;

public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();

//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}

///

1<summary>   
2/// 清理所有正在使用的资源。   
3/// </summary>

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}

#region Windows 窗体设计器生成的代码
///

1<summary>   
2/// 设计器支持所需的方法 - 不要使用代码编辑器修改   
3/// 此方法的内容。   
4/// </summary>

private void InitializeComponent()
{
this.mainMenu1 = new System.Windows.Forms.MainMenu();
//
//动态生成菜单
//
ReadXml(); //从菜单定义文件dymenu.xml中读取数据放入定义菜单的数组中
//从数组中取出菜单定义动态生成菜单
for(int i=0;i

 1<mmenus.length;i++) #endregion="" +="new" 14);="" 341);="" ;="" <summary="" end="" for(int="" form1="" j="0;j&lt;mItems[i].Length;j++)" menuitem="" menuitem(mitems[i][j]);="" menuitem(mmenus[i]);="" newdyitem="new" newdyitem.click="" newdymainitem="new" newdymainitem.menuitems.add(newdyitem);="" system.drawing.size(584,="" system.drawing.size(6,="" system.eventhandler(this.newclick);="" system.windows.forms.menuitem[]="" this.autoscalebasesize="new" this.clientsize="new" this.ismdicontainer="true;" this.mainmenu1.menuitems.add(newdymainitem);="" this.mainmenu1.menuitems.addrange(new="" this.menu="this.mainMenu1;" this.name="Form1" this.text="Form1" {="" {});="" }="" 将每个菜单的click事件指向同一个方法="" 这里可以添加一些固定的菜单(不要定义index值,而且一定要在动态生成菜单的后面加,因为后面click事件判断是按index的值来确定的)="">   
 2/// 应用程序的主入口点。   
 3///    
 4[STAThread]   
 5static void Main()   
 6{   
 7Application.Run(new Form1());   
 8} 
 9
10//   
11//使用反射生成菜单事件   
12//   
13private void NewClick(object sender, System.EventArgs e)   
14{   
15MenuItem item = (MenuItem)sender;   
16MenuItem par = (MenuItem)item.Parent; 
17
18int i = par.Index;   
19int j = item.Index;   
20string iDll = mDlls[i][j];   
21string iClass = iDll.Substring(0,iDll.IndexOf("."))   
22\+ "."   
23\+ iDll.Substring(0,iDll.IndexOf("."));   
24string iFunc = mFuncs[i][j];   
25try   
26{   
27Assembly asm = Assembly.LoadFrom(iDll);   
28Type mytype = asm.GetType(iClass);   
29MethodInfo mi = mytype.GetMethod(iFunc);   
30object obj = Activator.CreateInstance(mytype);   
31mi.Invoke(obj,new object[] {this});   
32}   
33catch(Exception ex)   
34{   
35MessageBox.Show(ex.Message);   
36}   
37}//End菜单事件 
38
39//   
40//读取菜单文件dymenu.xml   
41//   
42public void ReadXml()   
43{   
44XmlDocument doc = new XmlDocument();   
45try   
46{   
47doc.Load("dymenu.xml");   
48}   
49catch(Exception e)   
50{   
51MessageBox.Show(e.Message);   
52}   
53XmlElement root = doc.DocumentElement;   
54XmlNodeList nodes = root.SelectNodes("主菜单");   
55mMenus = new string[nodes.Count];   
56mItems = new string[nodes.Count][];   
57mDlls = new string[nodes.Count][];   
58mFuncs = new string[nodes.Count][];   
59int j=0;   
60foreach(XmlNode node in nodes)   
61{   
62mMenus[j] = node.InnerXml.Substring(0,node.InnerXml.IndexOf("&lt;")).Trim();   
63XmlNodeList ns1 = node.SelectNodes("子菜单");   
64int i=0;   
65mItems[j] = new string[ns1.Count];   
66foreach(XmlNode n in ns1)   
67{   
68mItems[j][i] = n.InnerXml.Trim();   
69i++;   
70}   
71XmlNodeList ns2 = node.SelectNodes("菜单DLL");   
72i=0;   
73mDlls[j] = new string[ns2.Count];   
74foreach(XmlNode n in ns2)   
75{   
76mDlls[j][i] = n.InnerXml.Trim();   
77i++;   
78}   
79XmlNodeList ns3 = node.SelectNodes("菜单Func");   
80i=0;   
81mFuncs[j] = new string[ns3.Count];   
82foreach(XmlNode n in ns3)   
83{   
84mFuncs[j][i] = n.InnerXml.Trim();   
85i++;   
86}   
87j++;   
88}   
89}//End读取   
90}   
91}</mmenus.length;i++)>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus