MSCE C++官网一步步学习搬运4

第四章、给MDL应用添加命令

 您可能已经注意到了MicroStation中存在着许多键入命令。在Home卡片的Primary组中能找到Key-in图标,可打开键入命令对话框,在这里可浏览并执行当前可用的所有键入命令,如下图所示。虽然该对话框中只列出了四栏,但实际上每个键入命令可由多于4个单词组成。

 这些键入命令有许多用途:比如在交互操作中可随时键入一个命令来实现操作的一个步骤;比如可以写一个由键入命令组成的脚本文件在MicroStation中直接执行;比如执行批处理功能时需要指定一个命令文件;再比如每个菜单项或工具栏中的每个图标工具,它们后台都关联着键入命令。可以这样说,键入命令是MicroStation图形用户界面与后台执行代码的重要纽带。以上列举的键入命令的四种用途分别如下图所示:

 

 

下面我们就一步步地在现有HelloWorld项目的基础上对其增加命令功能。

 1、在Visual Studio新建一个文本文件HelloWorldCmd.r,将如下内容复制到该文件中并保存。

#include <Mstn\MdlApi\rscdefs.r.h>
#include <Mstn\MdlApi\cmdclass.r.h>

/*----------------------------------------------------------------------+
|   Local Defines												
+----------------------------------------------------------------------*/
enum CmdTableIds
{
   CT_NONE = 0,
   CT_MAIN,
   CT_SUB,
   CT_CREATE
};
/*----------------------------------------------------------------------+
|   HelloWorld commands											
+----------------------------------------------------------------------*/
CommandTable   CT_MAIN =
{ 
    { 1,  CT_SUB,	PLACEMENT,	  REQ,		"HELLOWORLD" }, 
};
CommandTable	   CT_SUB =
{
    { 1,  CT_CREATE,    INHERIT,          NONE, 	"CREATE" },
};
CommandTable	   CT_CREATE =
{
    { 1,  CT_NONE, 	INHERIT, 	  DEF, 	        "Line" },
    { 2,  CT_NONE, 	INHERIT, 	  NONE,        "ComplexShape" },
    { 3,  CT_NONE, 	INHERIT, 	  NONE,        "ProjectedSolid" },
    { 4,  CT_NONE, 	INHERIT, 	  NONE,        "BsplineSurface",},
};

以上命令表文件定义了如下6个键入命令,它们分别有对应的命令号。

  

命名号

命令号的值

HelloWorld

CMD_HELLOWORLD

0x0100000000000000UI64

HelloWorld  Create

CMD_HELLOWORLD_CREATE

0x0101000000000000UI64

HelloWorld  Create  Line

CMD_HELLOWORLD_CREATE_LINE

0x0101010000000000UI64

HelloWorld  Create  ComplexShape

CMD_HELLOWORLD_CREATE_COMPLEXSHAPE

0x0101020000000000UI64

HelloWorld  Create  ProjectedSolid

CMD_HELLOWORLD_CREATE_PROJECTEDSOLID

0x0101030000000000UI64

HelloWorld  Create  BsplineSurface

CMD_HELLOWORLD_CREATE_BSPLINESURFACE

0x0101040000000000UI64

 对以上命令表文件做如下几点说明:

  • 需要包含两个必要的头文件rscdefs.r.h和cmdclass.r.h;
  • 通过enum定义了一些标识符CT_NONE、CT_MAIN、CT_SUB和CT_CREATE。当然也可直接通过#define来逐个定义。用enum的好处是能自动递增编号,不会发生重复定义的情况;
  • 每个命令表由CommandTable关键字定义,后跟一个命令表标识。命令表是一个动态数组,数组中的每行定义该级命令可用的关键字以及相关信息;
  • 命令表中的每行至少由五列组成(后续会使用到更多的列):第一列是索引值,第二列是子表标识,第三列是命令类别,第四列是命令选项,第五列是键入命令关键字。
  • 索引值构成了最终的命令号的值,命令类别在cmdclass.r.h中有定义,命令选项计有NONE、REQ(Required的缩写)、DEF(Default的缩写)、TRY(Try Parse)、HID(Hidden的缩写)以及IMM(Immediate的缩写)。

 2、在Visual Studio打开HelloWorld.mke文件并进行如下两处改动:

       a. 将第11行的appRscs = $(o)$(appName).rsc改为

             appRscs    = $(o)$(appName).rsc   $(o)$(appName)cmd.rsc

       b.将第46和48行前的注释符#删除。

             $(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中。

 3、下面要对HelloWorld.cpp进行多处改动:

       a. 包含HelloWorldCmd.h:

#include <Mstn\MdlApi\MdlApi.h>
#include <DgnPlatform\DgnPlatformApi.h>
#include "HelloWorldCmd.h"

b. 在MdlMain函数中删除原来的一些函数调用,增加命令号和命令处理函数动态数组定义、打开资源文件、装载命令表以及注册命令号等动作如下:

MdlCommandNumber cmdNums[] =
{
	{ (CmdHandler)createALine,		        CMD_HELLOWORLD_CREATE_LINE },
	{ (CmdHandler)createAComplexShape,	    CMD_HELLOWORLD_CREATE_COMPLEXSHAPE },
	{ (CmdHandler)createAProjectedSolid,	CMD_HELLOWORLD_CREATE_PROJECTEDSOLID },
	{ (CmdHandler)createABsplineSurface,    CMD_HELLOWORLD_CREATE_BSPLINESURFACE },
	0
};
extern "C" DLLEXPORT void MdlMain(int argc, WCharCP argv[])
{
	ModelInfoCP pInfo = ACTIVEMODEL->GetModelInfoCP();
	g_1mu = pInfo->GetUorPerStorage();

	RscFileHandle rscFileH;
	mdlResource_openFile(&rscFileH, NULL, RSC_READONLY);
	mdlParse_loadCommandTable(NULL);

	mdlSystem_registerCommandNumbers(cmdNums);
}

以上代码中的mdlResource_openFile会打开资源文件HelloWorld.ma,然后mdlParse_loadCommandTable从中装载命令表资源。 动态数组cmdNums中定义了命令处理函数和每个命令号的对应关系,然后由mdlSystem_registerCommandNumbers注册。我们没有像大多MDL例子中那样同时还定义一套命令名(需要用mdlSystem_registerCommandNames来注册),因为命令名的使用远没有键入命令来得方便。只有在您没有定义命令表的情况下才有必要使用命令名。

       c. 对createALine、createAComplexShape、createAProjectedSolid和createABsplineSurface进行一些改造以满足作为命令处理函数的要求。同时,将basePt的赋值内置在每个函数中。修改后的代码如下(省略掉了未改动部分):

以上代码中的mdlResource_openFile会打开资源文件HelloWorld.ma,然后mdlParse_loadCommandTable从中装载命令表资源。 动态数组cmdNums中定义了命令处理函数和每个命令号的对应关系,然后由mdlSystem_registerCommandNumbers注册。我们没有像大多MDL例子中那样同时还定义一套命令名(需要用mdlSystem_registerCommandNames来注册),因为命令名的使用远没有键入命令来得方便。只有在您没有定义命令表的情况下才有必要使用命令名。

       c. 对createALine、createAComplexShape、createAProjectedSolid和createABsplineSurface进行一些改造以满足作为命令处理函数的要求。同时,将basePt的赋值内置在每个函数中。修改后的代码如下(省略掉了未改动部分):

4、回到MicroStation CONNECT Edition SDK黑窗口界面,键入bmake生成项目。在生成项目的过程中,如果出现任何黄色或红色的提示信息则表示有警告或错误存在,需要消除后才能最终生成可执行的ma和dll。

 【注】:在执行bmake前一定要先到MicroStation软件中键入mdl unload helloworld卸载加载的应用,否则bmake时会出现无法覆盖原来的DLL的错误提示!!!

5、回到MicroStation中打开键入命令对话框,键入MDL LOAD HelloWorld装载应用,此时再输入HelloWorld后会看到如下图所示的命令键入树,这与我们在HelloWorldCmd.r中定义的完全对应。此时输入其中的一个命令并回车就能绘出相应的一部分图形。

猜你喜欢

转载自www.cnblogs.com/JolinZH/p/12820450.html