第四章、给MDL应用添加命令
您可能已经注意到了MicroStation中存在着许多键入命令。选菜单Utilities > Key-in可打开键入命令对话框,在这里可浏览并执行当前可用的所有键入命令,
如下图所示。虽然该对话框中只列出了四栏,但实际上每个键入命令最多可由5个单词组成。
这些键入命令有许多用途。比如在交互操作中可随时键入一个命令来实现操作的一个步骤,比如可以写一个由键入命令组成的脚本文件在MicroStation中直接执行,比如执行批处理功能时需要指定一个命令文件,再比如每个菜单项或工具栏中的每个图标工具,它们后台都关联着键入命令。可以这样说,键入命令是MicroStation图形用户界面与后台执行代码的重要纽带。以上列举的键入命令的四种用途分别如下图所示:
下面我们就一步步地在现有HelloWorld项目的基础上对其增加命令功能。
1. 在Visual Studio中打开您的HelloWorld项目,在解决方案浏览器中右击Resource Files文件夹并在弹出的菜单中选择Add New Item,在出现的窗体中找到并选中Text File (.txt)并在名称栏中输入HelloWorldCmd.r后点击Add按钮为当前工程添加一个空的.r文件。如下图所示:
2. 将如下命令表内容复制并粘贴到您的HelloWorldCmd.r文件中。保存该文件。
#include <rscdefs.h>
#include <cmdclass.h>
/*----------------------------------------------------------------------+
| Local Defines |
+----------------------------------------------------------------------*/
#define CT_NONE 0
#
define CT_MAIN 1
#define CT_SUB 2
#
define CT_CREATE 3
/*----------------------------------------------------------------------+
| HelloWorld commands |
+----------------------------------------------------------------------*/
/*----------------------------------------------------------------------+
| Table <tableId> = |
| { |
| { <no.>, <subTableId>, <cmdClass>, <options>, "<cmdWord>" }; | | }; |
+----------------------------------------------------------------------*/
Table CT_MAIN = { { 1, CT_SUB, PLACEMENT, REQ, "HelloWorld" }, };
Table CT_SUB = { { 1, CT_CREATE, INHERIT, REQ, "Create" }, };
Table CT_CREATE = { { 1, CT_NONE, INHERIT, NONE, "Line" },
{ 2, CT_NONE, INHERIT, NONE, "ComplexShape" },
{ 3, CT_NONE, INHERIT, NONE, "ProjectedSolid" },
{ 4, CT_NONE, INHERIT, NONE, "BsplineSurface" }, };
以上命令表文件定义了如下6个键入命令,它们分别有对应的命令号。
键 入 | 命名号 | 命令号的值 |
---|---|---|
HelloWorld | CMD_HELLOWORLD | 0x01000000 |
HelloWorld Create | CMD_HELLOWORLD_CREATE | 0x01010000 |
HelloWorld Create Line | CMD_HELLOWORLD_CREATE_LINE | 0x01010100 |
HelloWorld Create ComplexShape | CMD_HELLOWORLD_CREATE_COMPLEXSHAPE | 0x01010200 |
HelloWorld Create ProjectedSolid | CMD_HELLOWORLD_CREATE_PROJECTEDSOLID | 0x01010300 |
HelloWorld Create BsplineSurface | CMD_HELLOWORLD_CREATE_BSPLINESURFACE | 0x01010400 |
有关命令表的语法和各项的含义,请参见MDLProgrammerGuide帮助中的Compiling an Application Command Table 一节。
3. 在Visual Studio中双击HelloWorld.mke打开制作文件并进行如下两处改动:
a. 将第8行的appRscs = $(o)$(appName).rsc改为
appRscs = $(o)$(appName).rsc $(o)$(appName)cmd.rsc
b. 将第48和50行前的注释符#删除。
$(baseDir)$(appName)cmd.h : $(baseDir)$(appName)cmd.r
$(o)$(appName)cmd.rsc : $(baseDir)$(appName)cmd.r
【注】:以上代码中含有两个很重要的空行,不能随手删掉它们。空行表示按默认规则生成目标文件。在编译过程中bmake将会到mdl.mki文件中找到.r.h和.r.rsc规则去编译并生成HelloWorldCmd.h和HelloWorldCmd.rsc。HelloWorldCmd.h文件会在HelloWorld.cpp中引用,HelloWorldCmd.rsc被加入到appRscs宏定义中,从而最终被打包到HelloWorld.ma中。
4. 下面要对HelloWorld.cpp进行多处改动:
a. 包含HelloWorldCmd.h:
#include <MicroStationAPI.h>
#include <msdialog.fdf>
#include <mselmdsc.fdf>
#include <msbsplin.fdf>
#include "HelloWorldCmd.h"
b. 在MdlMain函数删除原来的一些函数调用,增加打开资源文件、装载命令表以及注册命令号等动作如下:
extern "C" DLLEXPORT int MdlMain (int argc, char *argv[])
{
g_1mu = mdlModelRef_getUorPerMaster(ACTIVEMODEL);
RscFileHandle rscFileH;
mdlResource_openFile (&rscFileH, NULL, RSC_READ);
mdlParse_loadCommandTable (NULL);
Private MdlCommandNumber commandNumbers [] =
{ {createALine, CMD_HELLOWORLD_CREATE_LINE},
{createAComplexShape, CMD_HELLOWORLD_CREATE_COMPLEXSHAPE},
{createAProjectedSolid, CMD_HELLOWORLD_CREATE_PROJECTEDSOLID},
{createABsplineSurface, CMD_HELLOWORLD_CREATE_BSPLINESURFACE},
0
};
mdlSystem_registerCommandNumbers (commandNumbers);
return 0;
}
以上代码中的mdlResource_openFile会打开资源文件HelloWorld.ma,然后mdlParse_loadCommandTable从中装载命令表资源。动态数组commandNumbers中定义了命令处理函数和每个命令号的对应关系,然后由mdlSystem_registerCommandNumbers注册。我们没有像大多MDL例子中那样同时还定义一套命令名,然后用mdlSystem_registerCommandNames来注册,因为命令名的使用远没有键入命令来得方便。只有在您没有定义命令表的情况下才有必要使用命令名。命令名的使用样例可参见SDK中的cellexp.cpp、gis.cpp和toolExample.cpp。
c. 对createALine、createAComplexShape、createAProjectedSolid和createABsplineSurface进行一些改造以满足作为命令处理函数的要求。同时,将basePt的赋值内置在每个函数中。修改后的代码如下(省略掉了未改动部分):
void createALine (char *unparsed)
{
MSElement myLine;
DPoint3d basePt={0,0,0}, pts[2];
pts[0] = pts[1] = basePt; ……
}
void createAComplexShape (char *unparsed)
{
MSElement el;
MSElementDescrP edP = NULL;
DPoint3d basePt, pts[3], tmpPt;
basePt.x = 1.7*g_1mu; basePt.y = -0.3*g_1mu;
basePt.z = -0.6*g_1mu; mdlComplexChain_createHeader (&el, 1, 0);
mdlElmdscr_new (&edP, NULL, &el); pts[0] = pts[1] = pts[2] = basePt; ……
}
void createAProjectedSolid (char *unparsed)
{
MSElement el;
MSElementDescrP sectionEdP = NULL, solidEdP = NULL;
DPoint3d basePt, pts[6], pt1, pt2;
basePt.x = 3.2*g_1mu; basePt.y = -0.6*g_1mu;
basePt.z = -1.2*g_1mu; pts[0] = basePt; ……
}
void createABsplineSurface (char *unparsed)
{
MSElement el;
MSElementDescrP edP = NULL;
MSBsplineSurface bsSurface;
MSBsplineCurve bsCurves[4];
DPoint3d basePt, arcPts[4][3];
basePt.x = 5.4*g_1mu; basePt.y = -2.3*g_1mu;
basePt.z = -1.8*g_1mu; arcPts[0][0] = arcPts[0][1] = arcPts[0][2] = basePt; ……
}
5. 在Visual Studio中选菜单Tools > Rebuild MDL App(Debug)生成项目,然后切换到MicroStation装载HelloWorld。
6. 选MicroStation主菜单Utilities > Key-in打开键入对话框,输入HelloWorld后会看到如下图所示的命令键入树,这与我们在HelloWorldCmd.r中定义的完全对应。此时输入其中的一个命令并回车就能绘出相应的一部分图形。