本文将从零开始教大家建立一个最简单的命令。这个命令是创建墙的命令。输入两个点,创建一堵墙。
在本例子中,我们使用系统自带的墙类型,也就是预先定义好的工程数据定义。如果需要在墙这个对象上增加更多的属性,则需要重新定制DataGroup,生成新的类型的墙对象。为了简单化,我们在这个例子中使用预先定义好的类型。
在硬盘D盘上建一个目录,名字是helloabd。使用文本编辑器,生成三个文件,文件名和内容分别是:
PolicyFile = MicroStationPolicy.mki
appName = helloabd
sAppName = helloabd
baseDir = $(_MakeFilePath)
baseDir = $(_MakeFilePath)
genSrc = $(o)
%include mdl.mki
mdlLibs = $(MSMDE)library/
abdLibs = $(ABDSDK)library/
always:
~mkdir $(o)
~mkdir $(rscObjects)
dirToSearch = $(MSMDE)include/
%include cincapnd.mki
dirToSearch = $(o)
%include cincapnd.mki
dirToSearch = $(ABDSDK)include/
%include cincapnd.mki
nameToDefine = HELLOABD_BUILD
%include cdefapnd.mki
DLM_NAME = $(appName)
DLM_OBJECT_DEST = $(o)
DLM_LIBDEF_SRC = $(_MakefilePath)
DLM_DEST = $(mdlapps)
DLM_NO_DLS = 1
DLM_NO_DEF = 1
DLM_NOENTRY = 1
DLM_NO_SIGN = 1
DLM_NO_MANIFEST = 1
DLM_OBJECT_FILES = \
$(o)$(appName)$(oext)
LINKER_LIBRARIES = $(mdlLibs)bentley.lib \
$(mdlLibs)BentleyAllocator.lib \
$(mdlLibs)mdlbltin.lib \
$(mdlLibs)RmgrTools.lib \
$(mdlLibs)BentleyGeom.lib \
$(mdlLibs)DgnPlatform.lib \
$(mdlLibs)dgnview.lib \
$(abdLibs)tfc.lib \
$(abdLibs)CatalogInstanceCollection.lib \
$(abdLibs)CatalogCollectionHelpers$(libExt)
#------------------------------------------------------------------------------
# Compile source files
#------------------------------------------------------------------------------
$(DLM_OBJECT_DEST)$(tstdir) : $(DLM_OBJECT_DEST)$(tstdir)
$(DLM_DEST)$(tstdir) : $(DLM_DEST)$(tstdir)
$(rscObjects)$(tstdir) : $(rscObjects)$(tstdir)
$(genSrc)$(appName)cmd.h : $(baseDir)$(appName)cmd.r
$(rscObjects)$(appName)cmd.rsc : $(baseDir)$(appName)cmd.r
$(o)$(appName)$(oext) : $(baseDir)$(appName).cpp
#---------------------------------------------
# link MDL Application
#---------------------------------------------
$(rscObjects)$(appName).mi : $(rscObjects)$(appName)cmd.rsc
$(msg)
> $(o)make.opt
-o$@
$(rscObjects)$(appName)cmd.rsc
<
$(RLibCmd) @$(o)make.opt
~time
#------------------------------------------------------------------------------
# Link the DLM
#------------------------------------------------------------------------------
%include dlmlink.mki
helloabdRscObjs = \
$(rscObjects)$(appName).mi
moreRscCompileOpts + -i$(basedir)
#------------------------------------------------------------------------------
# Create the final .ma (that holds just resources)
#------------------------------------------------------------------------------
MA_NAME = $(appName)
MA_DEST = $(DLM_DEST)
MA_RSC_FILES = $(helloabdRscObjs)
#---------------------------------------------
# Merge Objects into one file
#---------------------------------------------
$(DLM_DEST)$(MA_NAME).ma : $(helloabdRscObjs)
$(msg)
>$(o)make.opt
-o$@
$(helloabdRscObjs)
<
$(RLibCmd) @$(o)make.opt
~time
#include <DgnPlatform\DgnPlatformAPI.h>
#include <Mstn\MdlApi\MdlApi.h>
#include <DgnView\AccuDraw.h>
#include <DgnView\DgnElementSetTool.h>
USING_NAMESPACE_BENTLEY_DGNPLATFORM;
USING_NAMESPACE_BENTLEY_MSTNPLATFORM;
USING_NAMESPACE_BENTLEY_MSTNPLATFORM_ELEMENT;
#include <tfapi\mdltfmodelref.fdf>
#include <tfapi\mdltfform.fdf>
#include <tfapi\mdltflform.fdf>
#include <tfapi\mdltfwstring.fdf>
#include <tfapi\mdltfplane.fdf>
#include <tfapi\mdltfpoly.fdf>
#include <tfapi\mdltfpartref.fdf>
#include <tfapi\mdltfaform.fdf>
#include <tfapi\mdltflinestr.fdf>
#include <tfapi\mdltflsform.fdf>
#include <tfapi\mdltfslform.fdf>
#include <tfapi\mdltffrform.fdf>
#include <tfapi\mdltfpform.fdf>
#include <tfapi\mdltfbrep.fdf>
#include <tfapi\mdltfstform.fdf>
#include <tfapi\mdltfpart.fdf>
#include <tfapi\mdltfglobal.fdf>
#include <tfapi\mdltfelemen.fdf>
#include <tfapi/buildingEditElemHandle.h>
#include <tfapi/CatalogCollection.h>
#include <tfapi/ListModelHelper.h>
#include "helloabdcmd.h"
#ifdef HELLOABD_BUILD
#define HELLOABD_EXPORT __declspec (dllexport)
#else
#define HELLOABD_EXPORT __declspec (dllimport)
#endif
class HelloABDTool : public Bentley::DgnPlatform::DgnElementSetTool
{
HELLOABD_EXPORT virtual ~HelloABDTool () {}
public:
//! default constructor
HELLOABD_EXPORT HelloABDTool () : Bentley::DgnPlatform::DgnElementSetTool () { } // default constructor
// overrides
HELLOABD_EXPORT virtual bool _OnResetButton (DgnButtonEventCR ev) override
{
_OnRestartTool();
return false;
}
void SetupFamilyPart(TFFormRecipeLinear* pRecipe)
{
TFPartRefList* pPartRefNode = NULL;
mdlTFGlobal_getActivePartRef (&pPartRefNode);
mdlTFFormRecipe_setPartRef (pRecipe, mdlTFPartRefList_getPartRef (pPartRefNode));
mdlTFPartRefList_free (&pPartRefNode);
}
void Construct(TFFormRecipeLinearList* pRecipeNode, TFFormRecipeLinear* pRecipe, DPoint3d startPoint)
{
DVec3d sweepDir = DVec3d::From (0,0,1);
startPoint.y = 0;
startPoint.z = 0;
DPoint3d endPoint = startPoint;
endPoint.y = 10000;
mdlTFFormRecipeLinear_setTopFixedHeight (pRecipe, 10000);
mdlTFFormRecipeLinear_setThickness (pRecipe, 200);
mdlTFFormRecipeLinear_setOffsetType (pRecipe, FormRecipeOffsetTypeEnum_Left);
mdlTFFormRecipeLinear_setSweepDirection (pRecipe, &sweepDir);
mdlTFFormRecipeLinear_setEndPoints2 (pRecipe, &startPoint, &endPoint);
mdlTFFormRecipe_initLocalCoords (pRecipe);
SetupFamilyPart (pRecipe);
mdlTFFormRecipeList_synchronize (pRecipeNode);
mdlTFModelRef_addFormRecipeList (ACTIVEMODEL, pRecipeNode);
}
void SetupDataGroup(TFFormRecipeLinear* pRecipe)
{
ElementId id = mdlTFFormRecipe_getUniqueId (pRecipe);
EditElementHandle elm(id, ACTIVEMODEL);
Bentley::Building::Elements::BuildingEditElemHandle beeh (elm.GetElementRef (), ACTIVEMODEL);
CCatalogSchemaItemT* pSchemaItem = NULL;
beeh.GetCatalogCollection ().InsertDataGroupCatalogInstance (L"Wall", L"Brick");
beeh.GetCatalogCollection ().UpdateInstanceDataDefaults (L"Wall");
if (NULL != (pSchemaItem = beeh.GetCatalogCollection ().FindDataGroupSchemaItem (L"ObjectIdentity/@Description")))
pSchemaItem->SetValue (L"Bentley Wall Test");
beeh.Rewrite();
}
HELLOABD_EXPORT virtual bool _OnDataButton (DgnButtonEventCR ev) override
{
TFFormRecipeLinearList* pRecipeNode = mdlTFFormRecipeLinearList_construct ();
TFFormRecipeLinear* pRecipe = mdlTFFormRecipeLinearList_getFormRecipeLinear (pRecipeNode);
Construct (pRecipeNode, pRecipe, *ev.GetPoint ());
SetupDataGroup (pRecipe);
mdlTFFormRecipeLinearList_free (&pRecipeNode);
return false;
}
HELLOABD_EXPORT virtual void _OnRestartTool() override
{
HelloABDTool* pTool = new HelloABDTool ();
pTool->InstallTool ();
}
HELLOABD_EXPORT virtual void _OnPostInstall () override
{
__super::_OnPostInstall();
mdlLocate_init ();
mdlAccuSnap_enableSnap (TRUE);
mdlLocate_setCursor ();
mdlAccuSnap_enableLocate (true);
mdlAccuSnap_enableSnap (false);
mdlAccuSnap_suspend (false);
mdlAccuDraw_setEnabledState (false);
}
HELLOABD_EXPORT virtual StatusInt _OnElementModify(EditElementHandleR eh) override
{
return SUCCESS;
}
static void InstallNewInstance()
{
HelloABDTool* pTool = new HelloABDTool();
pTool->InstallTool();
}
};
int HelloABD
(
)
{
HelloABDTool::InstallNewInstance();
return 0;
}
MdlCommandNumber commandNumber[] =
{
{(CmdHandler) HelloABD, CMD_HELLOABD},
0
};
extern "C" DLLEXPORT void MdlMain
(
int argc,
WCharCP argv[]
)
{
RscFileHandle rfHandle;
mdlResource_openFile (&rfHandle, NULL, RSC_READONLY);
mdlSystem_registerCommandNumbers (commandNumber);
mdlParse_loadCommandTable (NULL);
}
#include <Mstn\MdlApi\rscdefs.r.h>
#include <Mstn\MdlApi\cmdclass.r.h>
#define CT_NONE 0
#define CT_HELLOABD 1
CommandTable CT_HELLOABD =
{
{ 1, CT_NONE, MANIPULATION, DEF, "helloabd"}
};
/*-----------------------------------------------------------------------
Setup for native code only MDL app
-----------------------------------------------------------------------*/
#define DLLAPP_HELLOABD 1
DllMdlApp DLLAPP_HELLOABD =
{
L"helloabd", L"helloabd"
};
打开桌面的ABD SDK快捷方式,在打开的Windows 命令行窗口中,输入命令
cd d:\helloabd bmake
编译成功。如果使用默认的安装目录,最终生成的helloabd.ma和helloabd.dll,会出现在:C:\Program Files\Bentley\AECOsim CONNECT Edition\AECOsimBuildingDesigner\Mdlapps 。测试可以在ABD中,打开命令行窗口,直接输入:mdl load abdhello 。测试命令:helloabd 。
首先打开Visual Studio 2015和ABD。在Visual Studio 2015中打开helloabd.cpp。然后在调试菜单中,点击:Attach to Process......
在视图中点击鼠标,会生成一个墙,如果没有看到,需要点击Fit View命令。这是我们用查看属性命令,就能看到新生成的墙的属性,和我们设计的是一样的。