在不重新编译主程序的情况下要对程序的功能进行扩充,我们可以使用动态生成菜单,将新增的窗体编译成dll文件,然后在主程序的菜单定义文件中注册,即可解决,以后程序升级,只需将对应的dll覆盖。
1.菜单定义文件可以使用ini或XML格式,这里使用的是XML格式
定义主菜单,子菜单,子菜单对应的dll,子菜单对应的函数
dymenu.xml内容如下
1<root>
2<主菜单>动态菜单1
3<子菜单>OpenForm1<!--子菜单-->
4<菜单DLL>MyForms.dll<!--菜单DLL-->
5<菜单Func>OpenForm1<!--菜单Func-->
6<子菜单>OpenForm2<!--子菜单-->
7<菜单DLL>MyForms.dll<!--菜单DLL-->
8<菜单Func>OpenForm2<!--菜单Func-->
9<!--主菜单-->
10<主菜单>动态菜单2
11<子菜单>OpenForm3<!--子菜单-->
12<菜单DLL>MyForms.dll<!--菜单DLL-->
13<菜单Func>OpenForm3<!--菜单Func-->
14<!--主菜单-->
15<主菜单>动态菜单3
16<子菜单>OpenForm4<!--子菜单-->
17<菜单DLL>MyForms.dll<!--菜单DLL-->
18<菜单Func>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<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("<")).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++)>