在不重新编译主程序的情况下要对程序的功能进行扩充,我们可以使用动态生成菜单,将新增的窗体编译成dll文件,然后在主程序的菜单定义文件中注册,即可解决,以后程序升级,只需将对应的dll覆盖。
1.菜单定义文件可以使用ini或XML格式,这里使用的是XML格式
定义主菜单,子菜单,子菜单对应的dll,子菜单对应的函数
dymenu.xml内容如下
<?xml version='1.0'?>
<ROOT>
<主菜单>动态菜单1
<子菜单>OpenForm1</子菜单>
<菜单DLL>MyForms.dll</菜单DLL>
<菜单Func>OpenForm1</菜单Func>
<子菜单>OpenForm2</子菜单>
<菜单DLL>MyForms.dll</菜单DLL>
<菜单Func>OpenForm2</菜单Func>
</主菜单>
<主菜单>动态菜单2
<子菜单>OpenForm3</子菜单>
<菜单DLL>MyForms.dll</菜单DLL>
<菜单Func>OpenForm3</菜单Func>
</主菜单>
<主菜单>动态菜单3
<子菜单>OpenForm4</子菜单>
<菜单DLL>MyForms.dll</菜单DLL>
<菜单Func>OpenForm4</菜单Func>
</主菜单>
</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
{
/// <summary>
/// Form1 的摘要说明。
/// </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;
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
/// <summary>
/// 清理所有正在使用的资源。
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
this.mainMenu1 = new System.Windows.Forms.MainMenu();
//
//动态生成菜单
//
ReadXml(); //从菜单定义文件dymenu.xml中读取数据放入定义菜单的数组中
//从数组中取出菜单定义动态生成菜单
for(int i=0;i<mMenus.Length;i++)
{
MenuItem newDyMainItem = new MenuItem(mMenus[i]);
this.mainMenu1.MenuItems.Add(newDyMainItem);
for(int j=0;j<mItems[i].Length;j++)
{
MenuItem newDyItem = new MenuItem(mItems[i][j]);
newDyMainItem.MenuItems.Add(newDyItem);
//将每个菜单的Click事件指向同一个方法
newDyItem.Click += new System.EventHandler(this.NewClick);
}
}//End
//这里可以添加一些固定的菜单(不要定义index值,而且一定要在动态生成菜单的后面加,因为后面Click事件判断是按index的值来确定的)
this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {});
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(584, 341);
this.IsMdiContainer = true;
this.Menu = this.mainMenu1;
this.Name = "Form1";
this.Text = "Form1";
}
#endregion
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
//
//使用反射生成菜单事件
//
private void NewClick(object sender, System.EventArgs e)
{
MenuItem item = (MenuItem)sender;
MenuItem par = (MenuItem)item.Parent;
int i = par.Index;
int j = item.Index;
string iDll = mDlls[i][j];
string iClass = iDll.Substring(0,iDll.IndexOf("."))
+ "."
+ iDll.Substring(0,iDll.IndexOf("."));
string iFunc = mFuncs[i][j];
try
{
Assembly asm = Assembly.LoadFrom(iDll);
Type mytype = asm.GetType(iClass);
MethodInfo mi = mytype.GetMethod(iFunc);
object obj = Activator.CreateInstance(mytype);
mi.Invoke(obj,new object[] {this});
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}//End菜单事件
//
//读取菜单文件dymenu.xml
//
public void ReadXml()
{
XmlDocument doc = new XmlDocument();
try
{
doc.Load("dymenu.xml");
}
catch(Exception e)
{
MessageBox.Show(e.Message);
}
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("主菜单");
mMenus = new string[nodes.Count];
mItems = new string[nodes.Count][];
mDlls = new string[nodes.Count][];
mFuncs = new string[nodes.Count][];
int j=0;
foreach(XmlNode node in nodes)
{
mMenus[j] = node.InnerXml.Substring(0,node.InnerXml.IndexOf("<")).Trim();
XmlNodeList ns1 = node.SelectNodes("子菜单");
int i=0;
mItems[j] = new string[ns1.Count];
foreach(XmlNode n in ns1)
{
mItems[j][i] = n.InnerXml.Trim();
i++;
}
XmlNodeList ns2 = node.SelectNodes("菜单DLL");
i=0;
mDlls[j] = new string[ns2.Count];
foreach(XmlNode n in ns2)
{
mDlls[j][i] = n.InnerXml.Trim();
i++;
}
XmlNodeList ns3 = node.SelectNodes("菜单Func");
i=0;
mFuncs[j] = new string[ns3.Count];
foreach(XmlNode n in ns3)
{
mFuncs[j][i] = n.InnerXml.Trim();
i++;
}
j++;
}
}//End读取
}
}