管華明
(安徽省水利水電勘測(cè)設(shè)計(jì)研究總院有限公司,安徽 合肥 230088)
MicroStation作為強(qiáng)大的基礎(chǔ)設(shè)計(jì)平臺(tái), 對(duì)大體量模型有良好支持,軟件底層對(duì)二次開(kāi)發(fā)的開(kāi)放和支持程度較好,運(yùn)行著眾多的適合水利水電行業(yè)相關(guān)專業(yè)的三維協(xié)同設(shè)計(jì)的專業(yè)軟件模塊。國(guó)內(nèi)部分具備研發(fā)實(shí)力的設(shè)計(jì)院基于MicroStation產(chǎn)品二次開(kāi)發(fā)出適用于本院業(yè)務(wù)邏輯的軟件或者工具集服務(wù)于實(shí)際生產(chǎn),提高設(shè)計(jì)效率,取得了一定成果。
目前,MicroStation平臺(tái)官方發(fā)布的軟件開(kāi)發(fā)包(SDK)主要支持4種類型的插件開(kāi)發(fā):MicroStation VBA(簡(jiǎn)稱MVBA,基于VB語(yǔ)言)、Addin(基于C#或其它的.NET開(kāi)發(fā)語(yǔ)言)、MDL(基于C++語(yǔ)言)、混合插件(基于C++/CLI語(yǔ)言)。MVBA最容易上手,適合開(kāi)發(fā)簡(jiǎn)單的小工具,開(kāi)發(fā)周期最短,但開(kāi)發(fā)出來(lái)的項(xiàng)目需要向最終用戶提供源代碼,對(duì)于保護(hù)知識(shí)產(chǎn)權(quán)不利。.NET接口存在封裝不全,部分接口不完善等問(wèn)題。MDL(基于C++)接口豐富功能最全,文檔相對(duì)詳細(xì)且包含大量的學(xué)習(xí)例子,但相對(duì)來(lái)說(shuō)復(fù)雜一些。
在MicroStation平臺(tái)上二次開(kāi)發(fā)大型復(fù)雜應(yīng)用應(yīng)首選MDL(基于C++語(yǔ)言)。.NET和VBA適合小型應(yīng)用或者工具類的開(kāi)發(fā)。如果要結(jié)合C++和.NET開(kāi)發(fā)各自的優(yōu)點(diǎn),可選用C++/CLI混合編程,但對(duì)開(kāi)發(fā)者的要求較高。
在基于C++語(yǔ)言的本機(jī)代碼應(yīng)用程序中,可以通過(guò)MicroStation應(yīng)用程序特有的r資源文件來(lái)添加圖形用戶界面,但文檔少、技術(shù)支持不足、沒(méi)有可視化的設(shè)計(jì)界面。一些完全開(kāi)源優(yōu)秀的框架以及圖形用戶界面模塊,如Qml、QtQuick等,技術(shù)成熟,有所見(jiàn)即所得的可視化設(shè)計(jì)界面及豐富的學(xué)習(xí)資料,真正做到了分離界面設(shè)計(jì)人員與開(kāi)發(fā)人員的工作,同時(shí)它為構(gòu)建用戶界面提供了許多全新的可視化組件、模型視圖支持、動(dòng)畫(huà)框架等,但未受MicroStation平臺(tái)原生支持,所以研究一種方法將Qml框架及QtQuick模塊用于在MicroStation平臺(tái)二次開(kāi)發(fā)中構(gòu)建用戶界面具有十分重要的意義。
為實(shí)現(xiàn)上述目的,將Qml框架用于MicroStation平臺(tái)二次開(kāi)發(fā)中構(gòu)建用戶界面, 包括下列實(shí)施步驟。
安裝Windows10 64位操作系統(tǒng),在系統(tǒng)中安裝MicroStation Connect Edition軟件及對(duì)應(yīng)的SDK開(kāi)發(fā)包,安裝5.15.x系列的Qt框架(由于Qt6.0以上版本依賴C++17語(yǔ)言標(biāo)準(zhǔn),但MicroStation最新版SDK只支持到C++14語(yǔ)言標(biāo)準(zhǔn),暫時(shí)無(wú)法使用Qt6.0以上版本的Qml框架)。
構(gòu)建動(dòng)態(tài)鏈接庫(kù)M1,實(shí)現(xiàn)在MicroStation應(yīng)用程序擁有事件循環(huán)的同時(shí)驅(qū)動(dòng)Qt事件循環(huán),并提供其余需要的類和函數(shù)。
(1)動(dòng)態(tài)鏈接庫(kù)M1中的類C1提供靜態(tài)API函數(shù)F1,如果MicroStation進(jìn)程中已經(jīng)有全局QApplication對(duì)象qApp,則函數(shù)F1什么也不做,返回false;否則函數(shù)F1安裝一個(gè)事件篩選器,實(shí)現(xiàn)在MicroStation應(yīng)用程序擁有事件循環(huán)的同時(shí)驅(qū)動(dòng)Qt事件循環(huán),并創(chuàng)建一個(gè)QApplication實(shí)例qApp。最后如果模塊M1在MicroStation進(jìn)程中已被加載,則函數(shù)顯式加載模塊M1以增加引用計(jì)數(shù)避免從內(nèi)存中卸載。類C1實(shí)現(xiàn)函數(shù)F1的流程如圖1所示。
圖1 類C1實(shí)現(xiàn)函數(shù)F1的流程
(2)創(chuàng)建QSettings全局對(duì)象Q1、全局句柄變量H1、H2。當(dāng)動(dòng)態(tài)鏈接庫(kù)M1被首次映射到了MicroStation進(jìn)程的地址空間時(shí),該模塊的入口函數(shù)調(diào)用步驟(1)中的函數(shù)F1,創(chuàng)建QSettings全局對(duì)象Q1用于記錄所有QtQuick應(yīng)用程序窗口的實(shí)時(shí)位置和大小,句柄變量H1、H2分別保存MicroStation宿主程序的主窗口句柄及圖標(biāo)句柄。
(3)動(dòng)態(tài)鏈接庫(kù)M1提供全局API函數(shù)F2,將MciroStation主窗口作為QtQuick應(yīng)用程序窗口的Owner窗口,實(shí)現(xiàn)了QtQuick應(yīng)用程序窗口浮顯于MciroStation主窗口上方,并且顯示時(shí)不會(huì)阻塞MicroStation宿主程序的消息,不影響用戶與宿主程序的其它交互。函數(shù)F2同時(shí)把QtQuick應(yīng)用程序窗口的圖標(biāo)設(shè)置成步驟(2)中的H2。如圖2所示。
圖2 動(dòng)態(tài)鏈接庫(kù)M1的主要功能接口
(4)動(dòng)態(tài)鏈接庫(kù)M1提供類C2,用于調(diào)整QtQuick窗口位置。QtQuick應(yīng)用程序窗口把該類對(duì)象注冊(cè)為事件過(guò)濾器,實(shí)現(xiàn)當(dāng)窗口移動(dòng)、關(guān)閉或銷毀時(shí),在步驟(2)中的Q1實(shí)時(shí)保存上一個(gè)窗口位置。QtQuick應(yīng)用程序窗口在構(gòu)造函數(shù)中調(diào)用類C2提供接口函數(shù)F3,把窗口位置調(diào)整為上一次的位置。
(5)動(dòng)態(tài)鏈接庫(kù)M1提供類C3,用于調(diào)整QtQuick窗口大小。QtQuick應(yīng)用程序窗口把該類對(duì)象注冊(cè)為事件過(guò)濾器,實(shí)現(xiàn)當(dāng)重新調(diào)整窗口大小時(shí),在步驟(2)的Q1實(shí)時(shí)保存上一次窗口大小。QtQuick應(yīng)用程序窗口在構(gòu)造函數(shù)中調(diào)用類C2提供接口函數(shù)F4,把窗口大小調(diào)整為上一次的大小。
(6)動(dòng)態(tài)鏈接庫(kù)M1提供全局API函數(shù)F5,把QtQuick應(yīng)用程序窗口的圖標(biāo)設(shè)置成步驟(2)中的主窗口圖標(biāo)H2。
(7)動(dòng)態(tài)鏈接庫(kù)M1提供全局API函數(shù)F6,用于宿主程序引入庫(kù)M1。
在二次開(kāi)發(fā)中使用QtQuick模塊構(gòu)建用戶界面主要流程如下:在程序中調(diào)用動(dòng)態(tài)鏈接庫(kù)M1中的函數(shù)F6,使MicroStation宿主程序把動(dòng)態(tài)鏈接庫(kù)M1引入進(jìn)程空間,并執(zhí)行類C1的靜態(tài)函數(shù)F1;創(chuàng)建基于QtQuick模塊的窗口類,在構(gòu)造函數(shù)中注冊(cè)事件過(guò)濾器,用于自動(dòng)實(shí)時(shí)保存窗口大小與位置,并加載上一次窗口的大小與位置數(shù)據(jù);創(chuàng)建窗口類的實(shí)例; 調(diào)用動(dòng)態(tài)鏈接庫(kù)M1中接口函數(shù)F2,設(shè)置窗口實(shí)例的Owner窗口以及圖標(biāo);顯示窗口類的實(shí)例。如圖3所示。
圖3 二次開(kāi)發(fā)中應(yīng)用QtQuick模塊流程
通過(guò)研發(fā)動(dòng)態(tài)鏈接庫(kù),實(shí)現(xiàn)了在MicroStation宿主程序擁有事件循環(huán)的同時(shí)驅(qū)動(dòng)Qt事件循環(huán);實(shí)現(xiàn)了將MciroStation主窗口作為QtQuick應(yīng)用程序窗口的Owner窗口,使QtQuick應(yīng)用程序窗口浮顯于MciroStation主窗口上方,不影響用戶與宿主程序的其它交互,這是將Qml框架用于MicroStation平臺(tái)二次開(kāi)發(fā)的關(guān)鍵技術(shù)要點(diǎn)。該技術(shù)方案對(duì)在其它基礎(chǔ)設(shè)計(jì)平臺(tái)二次開(kāi)發(fā)中使用Qml框架也具有重要借鑒意義。
由于Qt6.0以上版本依賴C++17語(yǔ)言標(biāo)準(zhǔn),但MicroStation最新版SDK只支持到C++14語(yǔ)言標(biāo)準(zhǔn), 本文還未解決如何使用Qt6.0以上版本的Qml框架。