1. 准备一个xml文件
xmlmenu
1<menu>
2 <menuitem name="系统管理" assemblyname="" formtag="false" addtoolbar="false">
3 <menuitem name="权限管理" shortcut="" image="" assemblyname="" formtag="false" addtoolbutton="false">
4 <menuitem name="系统权限管理" shortcut="" image="password.png" assemblyname="hustcad.inteplm.winui.frmsysright,inteplm.tyrightwinui"
formtag="true" addtoolbutton="false"/>
5 <menuitem name="权限规则定义" shortcut="" image="right.png" assemblyname="hustcad.inteplm.winui.frmrightrule,inteplm.tyrightwinui"
formtag="true" addtoolbutton="false"/>
6 <menuitem name="权限日志" shortcut="" image="doc_yellow_edit.png" assemblyname="hustcad.inteplm.winui.frmrightlog,inteplm.tyrightwinui"
formtag="true" addtoolbutton="false"/>
7 </menuitem>
8</menu>
2.准备一个xml schemal文件来验证xml文件
<?xml version="1.0" encoding="utf-8"?>
<!-- edited with xmlspy v2006 sp2 u (http://www.altova.com) by peter (hust) -->
<xs:schema xmlns:xs="http://www.w3.org/2001/xmlschema" elementformdefault="qualified">
<xs:element name="menu">
<xs:complextype>
<xs:sequence>
<xs:element ref="menuitem" maxoccurs="unbounded"/>
</xs:sequence>
</xs:complextype>
</xs:element>
<xs:element name="menuitem">
<xs:complextype>
<xs:sequence>
<xs:element ref="menuitem" minoccurs="0" maxoccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="addtoolbutton">
<xs:simpletype>
<xs:restriction base="xs:string">
<xs:enumeration value="true"/>
<xs:enumeration value="false"/>
</xs:restriction>
</xs:simpletype>
</xs:attribute>
<xs:attribute name="addtoolbar">
<xs:simpletype>
<xs:restriction base="xs:string">
<xs:enumeration value="true"/>
<xs:enumeration value="false"/>
</xs:restriction>
</xs:simpletype>
</xs:attribute>
<xs:attribute name="assemblyname" type="xs:string" use="required"/>
<xs:attribute name="formtag" use="required">
<xs:simpletype>
<xs:restriction base="xs:string">
<xs:enumeration value="true"/>
<xs:enumeration value="false"/>
</xs:restriction>
</xs:simpletype>
</xs:attribute>
<xs:attribute name="image" type="xs:string"/>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="shortcut" use="optional">
<xs:simpletype>
<xs:restriction base="xs:string">
<xs:enumeration value="f1"/>
<xs:enumeration value="f2"/>
<xs:enumeration value="f3"/>
<xs:enumeration value="f4"/>
<xs:enumeration value="f5"/>
<xs:enumeration value="f6"/>
<xs:enumeration value="f7"/>
<xs:enumeration value="f8"/>
<xs:enumeration value="f9"/>
<xs:enumeration value="f10"/>
<xs:enumeration value="f11"/>
<xs:enumeration value="f12"/>
<xs:enumeration value="alt0"/>
<xs:enumeration value="alt1"/>
<xs:enumeration value="alt2"/>
<xs:enumeration value="alt3"/>
<xs:enumeration value="alt4"/>
<xs:enumeration value="alt5"/>
<xs:enumeration value="alt6"/>
<xs:enumeration value="alt7"/>
<xs:enumeration value="alt8"/>
<xs:enumeration value="alt9"/>
<xs:enumeration value="altbksp"/>
<xs:enumeration value="altf1"/>
<xs:enumeration value="altf2"/>
<xs:enumeration value="altf3"/>
<xs:enumeration value="altf4"/>
<xs:enumeration value="altf5"/>
<xs:enumeration value="altf6"/>
<xs:enumeration value="altf7"/>
<xs:enumeration value="altf8"/>
<xs:enumeration value="altf9"/>
<xs:enumeration value="altf10"/>
<xs:enumeration value="altf11"/>
<xs:enumeration value="altf12"/>
<xs:enumeration value="altdownarrow"/>
<xs:enumeration value="altuparrow"/>
<xs:enumeration value="altleftarrow"/>
<xs:enumeration value="altrightarrow"/>
<xs:enumeration value="ctrl0"/>
<xs:enumeration value="ctrl1"/>
<xs:enumeration value="ctrl2"/>
<xs:enumeration value="ctrl3"/>
<xs:enumeration value="ctrl4"/>
<xs:enumeration value="ctrl5"/>
<xs:enumeration value="ctrl6"/>
<xs:enumeration value="ctrl7"/>
<xs:enumeration value="ctrl8"/>
<xs:enumeration value="ctrl9"/>
<xs:enumeration value="ctrla"/>
<xs:enumeration value="ctrlb"/>
<xs:enumeration value="ctrlc"/>
<xs:enumeration value="ctrld"/>
<xs:enumeration value="ctrle"/>
<xs:enumeration value="ctrlf"/>
<xs:enumeration value="ctrlg"/>
<xs:enumeration value="ctrlh"/>
<xs:enumeration value="ctrli"/>
<xs:enumeration value="ctrlj"/>
<xs:enumeration value="ctrlk"/>
<xs:enumeration value="ctrll"/>
<xs:enumeration value="ctrlm"/>
<xs:enumeration value="ctrln"/>
<xs:enumeration value="ctrlo"/>
<xs:enumeration value="ctrlp"/>
<xs:enumeration value="ctrlq"/>
<xs:enumeration value="ctrlr"/>
<xs:enumeration value="ctrls"/>
<xs:enumeration value="ctrlt"/>
<xs:enumeration value="ctrlu"/>
<xs:enumeration value="ctrlv"/>
<xs:enumeration value="ctrlx"/>
<xs:enumeration value="ctrly"/>
<xs:enumeration value="ctrlz"/>
<xs:enumeration value="ctrlf1"/>
<xs:enumeration value="ctrlf2"/>
<xs:enumeration value="ctrlf3"/>
<xs:enumeration value="ctrlf4"/>
<xs:enumeration value="ctrlf5"/>
<xs:enumeration value="ctrlf6"/>
<xs:enumeration value="ctrlf7"/>
<xs:enumeration value="ctrlf8"/>
<xs:enumeration value="ctrlf9"/>
<xs:enumeration value="ctrlf10"/>
<xs:enumeration value="ctrlf11"/>
<xs:enumeration value="ctrlf12"/>
<xs:enumeration value="ctrlins"/>
<xs:enumeration value="ctrlshift0"/>
<xs:enumeration value="ctrlshift1"/>
<xs:enumeration value="ctrlshift2"/>
<xs:enumeration value="ctrlshift3"/>
<xs:enumeration value="ctrlshift4"/>
<xs:enumeration value="ctrlshift5"/>
<xs:enumeration value="ctrlshift6"/>
<xs:enumeration value="ctrlshift7"/>
<xs:enumeration value="ctrlshift8"/>
<xs:enumeration value="ctrlshift9"/>
<xs:enumeration value="ctrlshifta"/>
<xs:enumeration value="ctrlshiftb"/>
<xs:enumeration value="ctrlshiftc"/>
<xs:enumeration value="ctrlshiftd"/>
<xs:enumeration value="ctrlshifte"/>
<xs:enumeration value="ctrlshiftf"/>
<xs:enumeration value="ctrlshiftg"/>
<xs:enumeration value="ctrlshifth"/>
<xs:enumeration value="ctrlshifti"/>
<xs:enumeration value="ctrlshiftj"/>
<xs:enumeration value="ctrlshiftk"/>
<xs:enumeration value="ctrlshiftl"/>
<xs:enumeration value="ctrlshiftm"/>
<xs:enumeration value="ctrlshiftn"/>
<xs:enumeration value="ctrlshifto"/>
<xs:enumeration value="ctrlshiftp"/>
<xs:enumeration value="ctrlshiftq"/>
<xs:enumeration value="ctrlshiftr"/>
<xs:enumeration value="ctrlshifts"/>
<xs:enumeration value="ctrlshiftt"/>
<xs:enumeration value="ctrlshiftu"/>
<xs:enumeration value="ctrlshiftv"/>
<xs:enumeration value="ctrlshiftw"/>
<xs:enumeration value="ctrlshiftx"/>
<xs:enumeration value="ctrlshifty"/>
<xs:enumeration value="ctrlshiftz"/>
<xs:enumeration value="shiftins"/>
<xs:enumeration value="shiftf1"/>
<xs:enumeration value="shiftf2"/>
<xs:enumeration value="shiftf3"/>
<xs:enumeration value="shiftf4"/>
<xs:enumeration value="shiftf5"/>
<xs:enumeration value="shiftf6"/>
<xs:enumeration value="shiftf7"/>
<xs:enumeration value="shiftf8"/>
<xs:enumeration value="shiftf9"/>
<xs:enumeration value="shiftf10"/>
<xs:enumeration value="shiftf11"/>
<xs:enumeration value="shiftf12"/>
<xs:enumeration value=""/>
</xs:restriction>
</xs:simpletype>
</xs:attribute>
</xs:complextype>
</xs:element>
</xs:schema>
3。定义一个类来加载菜单
public class menuload
{
private plugincollection m_plugins = null;
public menubar _menbar = new menubar();
public toolstrip _toolbar = new toolstrip();
private outlookbar bar = new outlookbar();
private imagelist imglist = new imagelist();
private stringbuilder builder = new stringbuilder();
public menuload()
{
bar = _menbar.outlookbar;
}
private tabcontrol tabctrl;
public tabcontrol tabctrl
{
set
{
tabctrl = value;
}
}
private void validationeventhandler(object sender, validationeventargs e)
{
builder.appendline("验证xml文档的时候发生错误:");
builder.appendline("严重级别:" + e.severity);
builder.appendline("错误信息:" + e.message);
builder.appendline("------+--------+-------+------+--------+-------+------+--------+-------+");
builder.appendline();
}
/**//// <summary>
/// 验证xml文件是否是合乎规范的文件
/// </summary>
/// <param name="xmlfile">文件名称</param>
/// <returns>是则返回true,否则返回false</returns>
private bool validatexml(string xmlfile)
{
bool validxml = false;
string spath = "";
spath = application.startuppath + "\\configurations\\xmlsmenu.xsd";
if(!system.io.file.exists(spath))
{
throw new system.io.filenotfoundexception(string.format(resources.stringfilenotfound, spath));
}
xmlreadersettings settings = new xmlreadersettings();
xmlschemaset schemaset = new xmlschemaset();
schemaset.add(null, spath);
settings.schemas.add(schemaset);
settings.validationtype = validationtype.schema;
settings.validationeventhandler += new validationeventhandler(validationeventhandler);
settings.validationflags = settings.validationflags | xmlschemavalidationflags.reportvalidationwarnings;
xmlreader reader = xmlreader.create(xmlfile, settings);
while(reader.read())
{
}
if(builder.length > 0)
{
validxml = false;
}
else
{
validxml = true;
}
reader.close();
return validxml;
}
/**//// <summary>
/// 加载菜单
/// </summary>
/// <param name="main">主菜单</param>
/// <param name="xmlfile">菜单定义文件</param>
public mainmenu loadmenus(string xmlfile)
{
mainmenu mainmenu = new mainmenu();
try
{
using(new waitcursor())
{
//验证xml是否是合乎规范的xml文件
if(validatexml(xmlfile))
{
xmldocument document = new xmldocument();
document.load(xmlfile);
xmlnode rootnode = document.documentelement;
mainmenu = getmenus(rootnode);
}
else
{
throw new exception(builder.tostring());
}
}
}
catch (system.io.filenotfoundexception)
{
utility.showerrormsg(string.format(resources.stringfilenotfound, xmlfile));
}
return mainmenu;
}
/**//// <summary>
/// 加载菜单
/// </summary>
/// <param name="main">主菜单</param>
/// <param name="node">菜单项节点</param>
private mainmenu getmenus(xmlnode node)
{
mainmenu mainmenu = new mainmenu();
list<xmlnode> nodelist= new list<xmlnode>();
list<officemenuitem> mnulist = new list<officemenuitem>();
list<iconpanel> iplist = new list<iconpanel>();
string menutext ="";
//首先加载主菜单,避免迭代的时候菜单显示的过分延迟。
foreach(xmlnode child in node.childnodes)
{
if(child.nodetype == xmlnodetype.element && child.name == "menuitem")
{
menutext = child.attributes["name"].value;
officemenuitem item = new officemenuitem(true,menutext);
mainmenu.menuitems.add(item);
iconpanel cp = new iconpanel();
bar.addband(menutext, cp);
nodelist.add(child);
mnulist.add(item);
iplist.add(cp);
}
}
//加载所有的子菜单
getsubmenus(iplist.toarray(),mnulist.toarray(), nodelist.toarray());
return mainmenu;
}
/**//// <summary>
/// 加载所有子菜单
/// </summary>
/// <param name="main">主菜单集合</param>
/// <param name="node">菜单节点集合</param>
private void getsubmenus(iconpanel[] iplist ,officemenuitem[] main, xmlnode[] node)
{
eventhandler handler = new eventhandler(onpluginclick);
eventhandler handler1 = new eventhandler(oniconclick);
eventhandler handler2 = new eventhandler(onbuttonclick);
string asmname;
string formtag;
string text;
menuclass mc;
xmlnode child;
string iconpath = "";
string iconname = "";
string msc = "";
for(int i = 0; i <= main.getupperbound(0); i++)
{
//foreach(xmlnode child in node[i].childnodes)
for(int j = 0; j < node[i].childnodes.count;j++ )
{
child = node[i].childnodes[j];
if(child.nodetype == xmlnodetype.element && child.name == "menuitem")
{
asmname = child.attributes["assemblyname"].value;
formtag = child.attributes["formtag"].value;
text = child.attributes["name"].value;
msc = child.attributes["shortcut"].value;
officemenuitem item = new officemenuitem(true, text, handler);
iconname = child.attributes["image"].value;
if(iconname != string.empty)
{
iconpath = themes.getcurrentthemepath() +iconname;
item.iconpath = iconpath;
}
mc = new menuclass();
mc.assemblyname = asmname;
mc.formtag = formtag;
item.tag = mc;
if(msc != string.empty)
{
item.shortcut = menushortcut.getshortcut(msc);
}
main[i].menuitems.add(item);
if((iconpath != string.empty) && system.io.file.exists(iconpath))
{ //添加按钮到outlookbar
panelicon picon = iplist[i].addicon(item.text,image.fromfile(iconpath),handler1);
picon.tag = mc;
//添加按钮到toolbar
toolstripbutton button = new toolstripbutton(item.text, image.fromfile(iconpath), handler2);
button.displaystyle = toolstripitemdisplaystyle.image;
button.tooltiptext = item.text;
button.tag = mc;
button.visible = true;
_toolbar.items.add(button);
}
iconpath = "";
mc = null;
if(child.childnodes.count > 0)
{
getchildmenu(iplist[i],item, child);
}
}
}
//添加分割线
toolstripseparator ss = new toolstripseparator();
_toolbar.items.add(ss);
}
}
/**//// <summary>
/// 加载子菜单
/// </summary>
/// <param name="parent">父菜单</param>
/// <param name="node">父菜单定义xml节点</param>
private void getchildmenu(iconpanel ip,officemenuitem parent, xmlnode node)
{
eventhandler handler = new eventhandler(onpluginclick);
eventhandler handler1 = new eventhandler(oniconclick);
eventhandler handler2 = new eventhandler(onbuttonclick);
menuclass mc;
string asmname;
string formtag;
string text;
xmlnode child1;
string iconpath = "";
string iconname = "";
string msc = "";
//foreach(xmlnode child1 in node.childnodes)
for(int i = 0; i < node.childnodes.count - 1;i++ )
{
child1 = node.childnodes[i];
//检查是否提供了类型
asmname = child1.attributes["assemblyname"].value;
formtag = child1.attributes["formtag"].value;
text = child1.attributes["name"].value;
officemenuitem childitem;
childitem = new officemenuitem(true, text, handler);
childitem.name = text;
mc = new menuclass();
mc.assemblyname = asmname;
mc.formtag = formtag;
childitem.tag = mc;
//添加快捷键
msc = child1.attributes["shortcut"].value;
if(msc != string.empty)
{
childitem.shortcut = menushortcut.getshortcut(msc);
}
//添加图标
iconname = child1.attributes["image"].value;
if(iconname != string.empty)
{
iconpath = themes.getcurrentthemepath() + iconname;
childitem.iconpath = iconpath;
}
parent.menuitems.add(childitem);
if((iconpath != string.empty) && system.io.file.exists(iconpath))
{ //添加按钮到outlookbar
panelicon picon = ip.addicon(childitem.text, image.fromfile(iconpath), handler1);
picon.tag = mc;
//添加按钮到toolbar
toolstripbutton button = new toolstripbutton(childitem.text, image.fromfile(iconpath), handler2);
button.displaystyle = toolstripitemdisplaystyle.image;
button.tooltiptext = childitem.text;
button.tag = mc;
button.visible = true;
_toolbar.items.add(button);
}
iconpath = "";
mc = null;
if(child1.childnodes.count > 0)
{
getchildmenu(ip,childitem, child1);
}
}
}
/**//// <summary>
/// 打开一个窗体
/// </summary>
/// <param name="asmname">窗体类程序集和窗体类的组合,从节点的assemblyname属性获取</param>
private void openform(menuclass mc)
{
string asmname = mc.assemblyname;
string formtag = mc.formtag;
if (formtag == "")
{
throw new exception(resources.stringnoformflag);
}
if(formtag.toupper() == "true")
{
if(asmname == string.empty)
{
throw new nullreferenceexception(resources.stringassemblynull);
}
//string[] a = asmname.split(',');
object obj = null;
type tp = type.gettype(asmname);
if(tp != null)
{
obj = activator.createinstance(tp);
}
else
{
throw new exception("加载程序的时候出错,请检查程序(dll,exe)是否存在或者类型是否正确。");
}
//检查是否是form类
if((obj == null) | !(obj is form))
{
throw new exception(resources.stringnotform);
}
form frm = (obj as form);
//检查打开的第一个窗口是否是mdiform
if(application.openforms[0].ismdicontainer)
{
//作为mdichildform
frm.mdiparent = application.openforms[0];
}
//加载窗体
frm.show();
}
}
/**//// <summary>
/// 菜单单击事件
/// </summary>
/// <param name="sender"></param>
/// <param name="args"></param>
private void onpluginclick(object sender, eventargs args)
{
officemenuitem item = (officemenuitem)sender;
menuclass mc = (menuclass) item.tag;
if ((item.text == "退出") | (item.text == "exit"))
{
onexitclick(sender, args);
return;
}
openform(mc);
}
}
这里面用到了delegate,最重要的函数是加载菜单的函数和onpluginclick函数。
使用这个框架可以动态增加任意的层次的模块。
微软的cab 使用resigster site方式来增加模块,感觉不是很方便。
以上就是一个简单的基于xml的模块集成框架的内容。