陳 真 尹燕運 馬宏毓 李士鋒 杜文曉
(中兵勘察設計研究院有限公司,北京 100053)
當前AutoCAD的二次開發(fā)語言主要有VisualLisp、VBA、ObjectARX和.NET API等,其中,VisualLisp與VBA較為簡單,但其功能相比ObjectARX較弱[1]。在AutoCAD提供的各種開發(fā)工具中,以C/C++開發(fā)的.arx程序的運行效率最高、功能最強。ObjectARX包含一組C/C++類庫,基于這些庫開發(fā)的程序與AutoCAD在同一地址空間內(nèi)運行并能直接訪問AutoCAD數(shù)據(jù)庫結構、圖形系統(tǒng)以及CAD幾何造型核心,能夠在運行期間實時擴展AutoCAD現(xiàn)有類及其功能。ObjectARX可以創(chuàng)建和AutoCAD固有命令一樣的新命令[2-3]。ObjectARX程序本質上是Windows動態(tài)鏈接庫(DLL)程序,與AutoCAD共享地址空間[4], ObjectARX可以監(jiān)控和處理AutoCAD的各種事件。
本研究擬通過軟件二次開發(fā),在AutoCAD中方便地錄入和獲取DWG圖上一百余顆古樹屬性信息。當鼠標移動到古樹符號上方時,以ToolTip方式顯示古樹信息,顯示的信息包括古樹的編碼、種類、學名、等級、年代、樹齡、樹高、胸/地圍、平均冠幅等,當鼠標離開古樹符號時信息框自動消失。
通過對比AutoCAD平臺幾種二次開發(fā)方式,通過采用C++語言,使用Visual Studio 2015開發(fā)環(huán)境,調用ObjectARX類庫,順利開發(fā)出本程序。本程序既滿足了客戶需求,也使我們在ObjectARX編程方面積累了更多經(jīng)驗。
ObjectARX程序的開發(fā)步驟在ObjectARX幫助文檔和相關的開發(fā)教程有詳述,不再贅述。開發(fā)者應注意:(1)要下載與自己AutoCAD軟件版本對應的ObjectARX SDK開發(fā)包,開發(fā)包里有全部的頭文件、.lib文件以及幫助文檔;(2)由于手動創(chuàng)建動態(tài)庫工程再配置參數(shù)容易出錯,在Visual Studio中盡量通過ObjectARX Wizards向導創(chuàng)建工程。
基于AutoCAD開發(fā)信息系統(tǒng),常用做法是將圖形信息存儲在DWG文件中,屬性信息存儲在外部數(shù)據(jù)庫中,中間通過ID關聯(lián)。本程序需要存儲的屬性信息較少,因此將屬性信息全部存儲在圖形的擴展數(shù)據(jù)XData中,不使用外部數(shù)據(jù)庫。存儲時將古樹的編碼、種類、學名、等級、年代、樹齡、樹高、胸/地圍、平均冠幅等信息之間用特殊分隔符分開。程序邏輯結構如圖1所示。
圖1 程序邏輯結構圖
基于ObjectARX開發(fā)的應用程序本身不是一個可單獨運行的程序, 而是作為AutoCAD的一個DLL動態(tài)鏈接庫[5],在需要的時候由AutoCAD動態(tài)加載。本程序基于ObjectARX進行二次開發(fā),根據(jù)前文所述設計思路,關鍵代碼如下。
(1)添加XData數(shù)據(jù)
struct resbuf* pRb;
//創(chuàng)建結果緩沖區(qū)鏈表
pRb = acutBuildList(AcDb::kDxfRegAppName, strAppName,AcDb::kDxfXdAsciiString, str,RTNONE);
AcDbEntity* pEnt;
pEnt->setXData(pRb);//添加XData
(2)刪除XData數(shù)據(jù)
//創(chuàng)建一個空的緩沖區(qū)鏈表rbnull
struct resbuf * rbnull = acutBuildList(AcDb::kDxfRegAppName, strAppName, RTNONE);
pEnt->setXData(rbnull);//刪除XData
(3)獲取XData數(shù)據(jù)
struct resbuf* pRb;
pRb = pEnt->xData(_T("古樹信息")); //獲取XData數(shù)據(jù),結果保存在pRb里
(4)修改XData數(shù)據(jù)
修改XData操作是先刪除現(xiàn)有的XData,然后再添加新的XData數(shù)據(jù),通過(2)、(1)代碼的組合來實現(xiàn)。
3.2 通過InputPointMonitor獲取Entity的XData古樹信息
監(jiān)聽鼠標移動并顯示古樹信息功能繼承自父類AcEdInputPointMonitor,在子類中重寫monitorInputPoint函數(shù),關鍵代碼如下:
AcEdInputPoint& input;//回調函數(shù)傳入的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;//回調函數(shù)傳入的AcEdInputPointMonitorResult對象
output.setAdditionalTooltipString(strend.c_str());//添加信息到Tooltip
3.4 ARX初始化時反應器的添加和卸載時移除
在acrxEntryPoint 函數(shù)的AcRx::kInitAppMsg 消息中添加反應器,添加反應器代碼如下:
inline AcApDocument* curDoc(){ return ::acDocManager->curDocument(); }
curDoc()->inputPointManager()->addPointMonitor(&myMonitor);
在acrxEntryPoint 函數(shù)的AcRx::kUnloadAppMsg消息中移除反應器,移除反應器代碼如下:
curDoc()->inputPointManager()->removePointMonitor(&myMonitor);
本程序基于ObjectARX 2018開發(fā),在AutoCAD2018里加載程序后,當鼠標移動到古樹上時,會以ToolTip形式顯示古樹信息,程序運行效果如圖2所示。
圖2 程序運行效果圖
基于ObjectARX2018實現(xiàn)了古樹信息錄入和瀏覽功能,在不使用外部數(shù)據(jù)庫的情況下滿足了用戶需求,避免了建設GIS系統(tǒng)和購買數(shù)據(jù)庫的額外支出,為用戶節(jié)約了使用成本。使用本程序可提高客戶的工作效率和使用體驗。
通過開發(fā)本程序,可進一步加深對ObjectARX 開發(fā)技術和運行機制的了解。在AutoCAD中把屬性信息存儲到圖形的XData里,并使用反應器以ToolTip方式顯示古樹信息的做法,符合當下廣泛使用的“大平臺+小程序”的開發(fā)模式。本程序在古樹信息錄入部分,如果使用VC++的MFC開發(fā)一個對話框為用戶提供輸入屬性,將進一步提高信息錄入的工作效率。