在不重新编译主程序的情况下要对程序的功能进行扩充,我们可以使用动态生成菜单,将新增的窗体编译成dll文件,然后在主程序的菜单定义文件中注册,即可解决,以后程序升级,只需将对应的dll覆盖。
1.菜单定义文件可以使用ini或XML格式,这里使用的是XML格式
定义主菜单,子菜单,子菜单对应的dll,子菜单对应的函数
dymenu.xml内容如下
<主菜单>动态菜单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>
主菜单>
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
{
///
/// Form1 的摘要说明。
///
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;
///
/// 必需的设计器变量。
///
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
///
/// 清理所有正在使用的资源。
///
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
///
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
///
private void InitializeComponent()
{
this.mainMenu1 = new System.Windows.Forms.MainMenu();
//
//动态生成菜单
//
ReadXml(); //从菜单定义文件dymenu.xml中读取数据放入定义菜单的数组中
//从数组中取出菜单定义动态生成菜单
for(int i=0;i { MenuItem newDyMainItem = new MenuItem(mMenus[i]); this.mainMenu1.MenuItems.Add(newDyMainItem); for(int j=0;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 /// /// 应用程序的主入口点。 /// [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读取 } }

