Addins和NativeCode类似,能支持键入命令。随着XML的流行,Addins中定义命令表不再使用MDL中的资源文件Table的格式,而是采用XML格式来定义。本章的主要内容之一就是详细介绍XML命令表的格式。其次,还要介绍如何将命令表嵌入Addin程序中以及在Addin程序中如何写处理命令的方法。
下面就一个具体的XML格式的命令表进行分析说明。该命令表来自Mstn SDK中的…\Bentley\MicroStationCONNECTSDK\examples\Elements\ManagedFenceExample\commands.xml。每个命令表中有且仅有一个KeyinTree节点,其下会有三个部分组成,分别为RootKeyinTable、SubKeyinTables和KeyinHandlers,它们分别表示命令的根键入表、子键入表以及命令键入对应的处理函数名称。
<?xml version="1.0" encoding="utf-8" ?> <KeyinTree xmlns="http://www.bentley.com/schemas/1.0/MicroStation/AddIn/KeyinTree.xsd"> <RootKeyinTable ID="root"> <Keyword SubtableRef="Commands" CommandWord="FENCEEXAMPLE"> <Options Required="true" /> </Keyword> </RootKeyinTable> <SubKeyinTables> <KeyinTable ID="Commands"> <Keyword SubtableRef="FromCmd" CommandWord="FROM"> <Options Required="true" /> </Keyword> <Keyword SubtableRef="ModifyCmd" CommandWord="MODIFY"> <Options Required="true" /> </Keyword> <Keyword CommandWord="CLEAR"> <Options Required="true" /> </Keyword> </KeyinTable> <KeyinTable ID="FromCmd"> <Keyword CommandWord="ELEMENT" /> <Keyword CommandWord="POINTS" /> </KeyinTable> <KeyinTable ID="ModifyCmd"> <Keyword CommandWord="MOVE"/> <Keyword CommandWord="CLIP"/> <Keyword CommandWord="STRETCH"/> </KeyinTable> </SubKeyinTables> <KeyinHandlers> <KeyinHandler Keyin="FENCEEXAMPLE FROM ELEMENT" Function="ManagedFenceExample.Keyin.CmdPlaceFenceFromElement"/> <KeyinHandler Keyin="FENCEEXAMPLE FROM POINTS" Function="ManagedFenceExample.Keyin.CmdPlaceFenceFromPoints"/> <KeyinHandler Keyin="FENCEEXAMPLE CLEAR" Function="ManagedFenceExample.Keyin.CmdClearFence"/> <KeyinHandler Keyin="FENCEEXAMPLE MODIFY MOVE" Function="ManagedFenceExample.Keyin.CmdMoveFenceContents"/> <KeyinHandler Keyin="FENCEEXAMPLE MODIFY CLIP" Function="ManagedFenceExample.Keyin.CmdClipFenceContents"/> <KeyinHandler Keyin="FENCEEXAMPLE MODIFY STRETCH" Function="ManagedFenceExample.Keyin.CmdStretchFenceContents"/> </KeyinHandlers> </KeyinTree>
在<RootKeyinTable>和<KeyinTable>中有属性ID,表示该表的名称。命令表的内容由一个或多个<Keyword>元素组成,<Keyword>属性SubtableRef指向其下级命令表的ID。这样,通过当前表中<Keyword>的SubtableRef和下级表中<KeyinTable>的ID就能构成一个命令树。Mstn中的命令由一到五个单词组成,因而,我们在定义自己的commands.xml时在<SubKeyinTables>段中最多可以定义四级命令。<Keyword>还必须有属性CommandWord,这是用户在Mstn键入域中可输入的单词。<Keyword>有一个属性CommandClass表示该键入命令对应的命令类别,目前支持的命令类别有Placement、Viewing、Fence、Parameters、Locks、MacroCommand、Manipulation等。命令类别还可以是Inherit,表示继承上个命令单词所属的命令类别。<Keyword>中还可以包含<Options>项,该项是对<Keyword>的进一步说明,其属性有Required、Default、TryParse、Hidden等。Required="true"表示该命令字不是最后一个单词,必须有下级子节点;Default="true"表示该命令字为默认,当省略这一级命令字时取该命令字,在同一级别中只能有一个命令字为Default。TryParse="true"表示该命令字后可跟用户输入的任意字符,这些不在命令表中的字符串将被传递到命令处理函数的unparsed参数中。比如Active Color命令后可跟Red、Green、Blue等,也可以跟一个数字,如Active Color 245。我们不可能在命令表中列出每个这样的键入,此时可用TryParse属性;Hidden="true"表示该命令隐藏,用户在Mstn的命令浏览器中看不到该命令,但该命令仍然有效。这些隐藏的命令往往为程序所用或暂时不想对用户公开。
<KeyinHandlers>段只有<KeyinHandler>一种元素。其中的Keyin属性表示完整的键入命令字符串,<KeyinHandler>的Function属性为该键入命令对应的处理函数名,该函数名由命名空间名、类名和函数名(或称方法名)三部分组成。换句话说,当用户在Mstn中输入Keyin中的字符串时,就会调用到Function指定的函数。
下面我们来一步步改造csAddins使其支持键入命令。
1.在VS中打开您的csAddins项目,选菜单Project > Add New Item (当然也可以像以前我们介绍的那样,右击项目名称后在弹出的菜单中选择Add New Item),在出现的窗体中找到并选中XML File并在名称栏中输入commands.xml后点击Add按钮为当前工程添加一个空的XML文件。如下图所示:
2.将如下命令表内容复制并粘贴到您的commands.xml文件中。
<?xml version="1.0" encoding="utf-8" ?> <KeyinTree xmlns="http://www.bentley.com/schemas/1.0/MicroStation/AddIn/KeyinTree.xsd"> <RootKeyinTable ID="root"> <Keyword SubtableRef="CreateElement" CommandClass="MacroCommand" CommandWord="csAddins" > <Options Required="true"/> </Keyword> </RootKeyinTable> <SubKeyinTables> <KeyinTable ID="CreateElement"> <Keyword SubtableRef="Commands" CommandWord="CreateElement"> <Options Required="true"/> </Keyword> </KeyinTable> <KeyinTable ID="Commands"> <Keyword CommandWord="LineAndLineString1"> </Keyword> <Keyword CommandWord="LineAndLineString2"> </Keyword> <Keyword CommandWord="LineAndLineString3"> </Keyword> <Keyword CommandWord="ShapeAndComplexShape"> </Keyword> <Keyword CommandWord="TextString"> </Keyword> <Keyword CommandWord="Cell"> </Keyword> <Keyword CommandWord="Dimension"> </Keyword> <Keyword CommandWord="BsplineCurve"> </Keyword> <Keyword CommandWord="Cone"> </Keyword> </KeyinTable> </SubKeyinTables> <KeyinHandlers> <KeyinHandler Keyin="csAddins CreateElement LineAndLineString1" Function="csAddins.CreateElement.LineAndLineString1"/> <KeyinHandler Keyin="csAddins CreateElement LineAndLineString2" Function="csAddins.CreateElement.LineAndLineString2"/> <KeyinHandler Keyin="csAddins CreateElement LineAndLineString3" Function="csAddins.CreateElement.LineAndLineString3"/> <KeyinHandler Keyin="csAddins CreateElement ShapeAndComplexShape" Function="csAddins.CreateElement.ShapeAndComplexShape"/> <KeyinHandler Keyin="csAddins CreateElement TextString" Function="csAddins.CreateElement.TextString"/> <KeyinHandler Keyin="csAddins CreateElement Cell" Function="csAddins.CreateElement.Cell"/> <KeyinHandler Keyin="csAddins CreateElement Dimension" Function="csAddins.CreateElement.Dimension"/> <KeyinHandler Keyin="csAddins CreateElement BsplineCurve" Function="csAddins.CreateElement.BsplineCurve"/> <KeyinHandler Keyin="csAddins CreateElement Cone" Function="csAddins.CreateElement.Cone"/> </KeyinHandlers> </KeyinTree>
3.在解决方案浏览器中右击commands.xml并选择Properties菜单打开属性窗体,设置Build Action (生成动作) 为 Embeded Resource (嵌入资源) 。这样,command.xml文件将会被嵌入到csAddins.dll中。如下图所示:
4.用Notapad++打开项目配置文件D:\Files\BentleyMstn\MstnCE\Addins\csAddins\csAddins\csAddins.csproj,找到“<EmbeddedResource Include="commands.xml" />”这一行改为如下内容:
<EmbeddedResource Include="Commands.xml"> <SubType>Designer</SubType> <LogicalName>CommandTable.xml</LogicalName> </EmbeddedResource>
【注】:修改这个csproj时,一定要取消<EmbeddedResource>标签行尾的那个/符号。该符号是对于无内容的XML标签的结束符。我们现在添加了<LogicalName>标签后就需要用单独的</EmbeddedResource>来结束了。
5.对MyAddins.cs进行两处修改:5a) 在class MyAddin行前增加AddIn属性定义,指定MdlTaskID;5b) 注释或删除掉Run函数的所有内容,仅留下return 0一行。修改后的类定义如下:
[AddIn(MdlTaskID = "csAddins")] internal sealed class MyAddin : AddIn { public static MyAddin Addin = null; private MyAddin(System.IntPtr mdlDesc) : base(mdlDesc) { Addin = this; } protected override int Run(string[] commandLine) { return 0; } }
6.修改CreateElement.cs中的每个函数的说明,使其带有一个string类型的参数。如:
//用户可以在key-in命令后边以空格为分割符加一些字符串来传递一些额外的信息,此字符串作为命令函数的参数传递给函数 public static void LineAndLineString1(string unparsed) { …… } public static void ShapeAndComplexShape(string unparsed) { …… }
7.在VS中生成项目,然后切换到Mstn装载csAddins程序集(详细步骤可参见前几章的介绍)。因为我们删除了MyAddins.cs中Run函数中的所有执行语句,所以,加载程序集后并没有绘出任何图形。
8.打开Key-in键入对话框,输入csaddins后会看到如下图所示的命令键入树,这与我们在commands.xml中的完全对应。此时输入其中的一个命令并回车就能绘出相应的一部分图形。如输入csaddins createelement cone将只会绘出如下图形:
通过以上练习您已经掌握了如何给Addin应用程序添加命令,CE之前的SDK中有一个检查命令表XML文件正确性的工具UstnXOM.exe。有关此工具的使用介绍可参考Learning MicroStation Addins Step by Step[4]
在CE下,可参考如下文章来及时检验该命令XML文件语法的合法性: