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文件语法的合法性: