陈 真 尹燕运 马宏毓 李士锋 杜文晓
(中兵勘察设计研究院有限公司,北京 100053)
当前AutoCAD的二次开发语言主要有VisualLisp、VBA、ObjectARX和.NET API等,其中,VisualLisp与VBA较为简单,但其功能相比ObjectARX较弱[1]。在AutoCAD提供的各种开发工具中,以C/C++开发的.arx程序的运行效率最高、功能最强。ObjectARX包含一组C/C++类库,基于这些库开发的程序与AutoCAD在同一地址空间内运行并能直接访问AutoCAD数据库结构、图形系统以及CAD几何造型核心,能够在运行期间实时扩展AutoCAD现有类及其功能。ObjectARX可以创建和AutoCAD固有命令一样的新命令[2-3]。ObjectARX程序本质上是Windows动态链接库(DLL)程序,与AutoCAD共享地址空间[4], ObjectARX可以监控和处理AutoCAD的各种事件。
本研究拟通过软件二次开发,在AutoCAD中方便地录入和获取DWG图上一百余颗古树属性信息。当鼠标移动到古树符号上方时,以ToolTip方式显示古树信息,显示的信息包括古树的编码、种类、学名、等级、年代、树龄、树高、胸/地围、平均冠幅等,当鼠标离开古树符号时信息框自动消失。
通过对比AutoCAD平台几种二次开发方式,通过采用C++语言,使用Visual Studio 2015开发环境,调用ObjectARX类库,顺利开发出本程序。本程序既满足了客户需求,也使我们在ObjectARX编程方面积累了更多经验。
ObjectARX程序的开发步骤在ObjectARX帮助文档和相关的开发教程有详述,不再赘述。开发者应注意:(1)要下载与自己AutoCAD软件版本对应的ObjectARX SDK开发包,开发包里有全部的头文件、.lib文件以及帮助文档;(2)由于手动创建动态库工程再配置参数容易出错,在Visual Studio中尽量通过ObjectARX Wizards向导创建工程。
基于AutoCAD开发信息系统,常用做法是将图形信息存储在DWG文件中,属性信息存储在外部数据库中,中间通过ID关联。本程序需要存储的属性信息较少,因此将属性信息全部存储在图形的扩展数据XData中,不使用外部数据库。存储时将古树的编码、种类、学名、等级、年代、树龄、树高、胸/地围、平均冠幅等信息之间用特殊分隔符分开。程序逻辑结构如图1所示。
图1 程序逻辑结构图
基于ObjectARX开发的应用程序本身不是一个可单独运行的程序, 而是作为AutoCAD的一个DLL动态链接库[5],在需要的时候由AutoCAD动态加载。本程序基于ObjectARX进行二次开发,根据前文所述设计思路,关键代码如下。
(1)添加XData数据
struct resbuf* pRb;
//创建结果缓冲区链表
pRb = acutBuildList(AcDb::kDxfRegAppName, strAppName,AcDb::kDxfXdAsciiString, str,RTNONE);
AcDbEntity* pEnt;
pEnt->setXData(pRb);//添加XData
(2)删除XData数据
//创建一个空的缓冲区链表rbnull
struct resbuf * rbnull = acutBuildList(AcDb::kDxfRegAppName, strAppName, RTNONE);
pEnt->setXData(rbnull);//删除XData
(3)获取XData数据
struct resbuf* pRb;
pRb = pEnt->xData(_T("古树信息")); //获取XData数据,结果保存在pRb里
(4)修改XData数据
修改XData操作是先删除现有的XData,然后再添加新的XData数据,通过(2)、(1)代码的组合来实现。
3.2 通过InputPointMonitor获取Entity的XData古树信息
监听鼠标移动并显示古树信息功能继承自父类AcEdInputPointMonitor,在子类中重写monitorInputPoint函数,关键代码如下:
AcEdInputPoint& input;//回调函数传入的AcEdInputPoint对象
AcDbEntity* pEnt;
acdbOpenAcDbEntity(pEnt, input.pickedEntities().at(0), AcDb::kForRead);
struct resbuf* pRb;
pRb = pEnt->xData(_T("古树信息")); //获取到Entity的Xdata古树信息
3.3 获取的古树信息使用InputPointMonitorResult的方法显示到Tooltip中
wstring strend ;//存储从Xdata获取的古树信息的字符串
AcEdInputPointMonitorResult& output;//回调函数传入的AcEdInputPointMonitorResult对象
output.setAdditionalTooltipString(strend.c_str());//添加信息到Tooltip
3.4 ARX初始化时反应器的添加和卸载时移除
在acrxEntryPoint 函数的AcRx::kInitAppMsg 消息中添加反应器,添加反应器代码如下:
inline AcApDocument* curDoc(){ return ::acDocManager->curDocument(); }
curDoc()->inputPointManager()->addPointMonitor(&myMonitor);
在acrxEntryPoint 函数的AcRx::kUnloadAppMsg消息中移除反应器,移除反应器代码如下:
curDoc()->inputPointManager()->removePointMonitor(&myMonitor);
本程序基于ObjectARX 2018开发,在AutoCAD2018里加载程序后,当鼠标移动到古树上时,会以ToolTip形式显示古树信息,程序运行效果如图2所示。
图2 程序运行效果图
基于ObjectARX2018实现了古树信息录入和浏览功能,在不使用外部数据库的情况下满足了用户需求,避免了建设GIS系统和购买数据库的额外支出,为用户节约了使用成本。使用本程序可提高客户的工作效率和使用体验。
通过开发本程序,可进一步加深对ObjectARX 开发技术和运行机制的了解。在AutoCAD中把属性信息存储到图形的XData里,并使用反应器以ToolTip方式显示古树信息的做法,符合当下广泛使用的“大平台+小程序”的开发模式。本程序在古树信息录入部分,如果使用VC++的MFC开发一个对话框为用户提供输入属性,将进一步提高信息录入的工作效率。