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