在不重新编译主程序的情况下要对程序的功能进行扩充,我们可以使用动态生成菜单,将新增的窗体编译成dll文件,然后在主程序的菜单定义文件中注册,即可解决,以后程序升级,只需将对应的dll覆盖。
1.菜单定义文件可以使用ini或XML格式,这里使用的是XML格式
定义主菜单,子菜单,子菜单对应的dll,子菜单对应的函数
dymenu.xml内容如下
<主菜单>动态菜单1 <子菜单>OpenForm1 <菜单dll>MyForms.dll <菜单func>OpenForm1 <子菜单>OpenForm2 <菜单dll>MyForms.dll <菜单func>OpenForm2
<主菜单>动态菜单2 <子菜单>OpenForm3 <菜单dll>MyForms.dll <菜单func>OpenForm3
<主菜单>动态菜单3 <子菜单>OpenForm4 <菜单dll>MyForms.dll <菜单func>OpenForm4
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("<> 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读取 } }
|