鄭恢康 朱 偉
(中國電子科技集團公司第四十一研究所 山東 青島 266555)
目前很多電子測量儀器,如示波器、頻譜分析儀、矢量網(wǎng)絡分析儀等,其測量結果以曲線形式進行顯示。這些儀器軟件通常包括數(shù)據(jù)采集、數(shù)據(jù)處理、數(shù)據(jù)顯示3部分。動態(tài)波形的繪制是測試儀器中極為重要的一環(huán)[1]。其用于實現(xiàn)數(shù)據(jù)顯示的繪圖模塊具有較多共通性,含有窗口、多跡線、信息顯示、光標等要素。但因繪圖模塊和系統(tǒng)其他部份相互關聯(lián)(例如:繪圖模塊調(diào)用采集模塊獲得測量數(shù)據(jù)),且以源碼的形式嵌入整個系統(tǒng)中,使得繪圖相關的代碼難以復用[2]。
針對上述設計的不足,本文從通用性和復用性的角度出發(fā),應用面向對象的組件化軟件設計方法,設計并實現(xiàn)了一種通用的繪圖模塊。該模塊基于動態(tài)鏈接庫(DLL)技術,方便地實現(xiàn)復用、集成和擴展,滿足測量儀器領域的繪圖需求,提高軟件開發(fā)效率。
通用繪圖模塊是在Windows下使用Visual Studio 2008開發(fā)環(huán)境, C++語言開發(fā)實現(xiàn)的,它基于MFC類庫實現(xiàn)圖形繪制功能。因此,需在開發(fā)環(huán)境中創(chuàng)建一個“MFC常規(guī)DLL”工程,最終經(jīng)編譯得到Dll和Lib文件,與相關的頭文件一起提供給用戶。
設計通用繪圖模塊有兩個關鍵點:一是避免模塊依賴于軟件系統(tǒng),使模塊獨立;二是支持擴展繪圖,滿足特殊的繪圖需求。
為了使模塊獨立,模塊應設計成由上層配置、調(diào)用、啟動的方式,而減少模塊對軟件系統(tǒng)的調(diào)用[3]。另外,應用面向對象編程依賴倒置的原則[4],使系統(tǒng)與模塊之間不直接依賴于具體實現(xiàn),而是依賴于接口。
為支持繪圖擴展,應用面向對象編程開閉原則,在模塊內(nèi)實現(xiàn)共通的、基本的繪圖功能,其他繪圖則通過繪圖組件的方式進行擴展實現(xiàn),使模塊向修改關閉,向擴展開放[5]。
對于電子測量儀器領域,基本繪圖任務就是曲線的繪制,另外該領域通常以光標的方式進行測量數(shù)據(jù)的讀取與顯示,這兩部份可作為基本繪圖需求在模塊內(nèi)實現(xiàn)。而系統(tǒng)功能中涉及到的一些特殊繪圖需求,例如提示信息、參數(shù)設置框等,可透過繪圖組件的形式來實現(xiàn)。
基于以上分析,定義以下主要類:
(1) 繪圖接口類CGraphInterface繪圖模塊對外提供的訪問接口。
(2) 繪圖類CGraph實現(xiàn)對跡線、光標、繪圖組件的管理。
(3) 繪圖組件接口CGComponentInf用戶繼承該接口定制繪圖組件,并將指針傳給繪圖類,由繪圖類進行繪制。
(4) 跡線類CTrace實現(xiàn)跡線數(shù)據(jù)及網(wǎng)格等的繪制。
(5) 光標管理類CMarkerManager實現(xiàn)光標功能,用于繪制光標和光標信息,顯示測量數(shù)值。
這幾個主要類之間的關系如圖1所示。
圖1 繪圖模塊UML類圖
另外,對于測量儀器,通常要繪制動態(tài)跡線,為了避免繪圖時閃爍,可采用雙緩沖繪圖技術[6],在CGraph類中實現(xiàn)。
該模塊完成測量跡線、坐標網(wǎng)格、刻度標尺等的繪制,將這些視為跡線的屬性,封裝為CTrace類。
2.1.1CGraph類相關設計
為支持多跡線的繪置,在CGraph類組合CTrace類的成員變量,CGraph內(nèi)部調(diào)用CTrace接口進行跡線相關圖形繪制,CGraph對外提供相應的接口進行跡線相關配置。
在CGraph中定義成員變量:
CList
在CGraph中定義跡線操作接口:
(1) 添加跡線void AddTrace(CArray
其中data為傳入的繪圖數(shù)據(jù),nTrID為上層為該跡線分配的ID,Graph其他接口通過該ID對指定跡線進行相關操作。
(2) 刪除跡線void DeleteTrace(int nTrID);
(3) 設置跡線刻度void SetTraceScale(double fTop,double fBtm,int nTrID);
(4) 選擇當前跡線void SelectCurTrace(int nTrID);
2.1.2CTrace類設計
CTrace類主要實現(xiàn)測量的數(shù)據(jù)坐標轉換,以及網(wǎng)格、標尺相關的繪制。
CTrace類定義成員變量,對原始數(shù)據(jù)和轉換后的繪圖數(shù)據(jù)進行存放:
CArray
CArray
為支持對多種的坐標格式,應用面向對象編程多態(tài)技術[7-8],將與坐標、及坐標轉換相關的函數(shù)定義為虛函數(shù),在CTrace派生類中實現(xiàn)。
virtual void DrawGrid(CDC* pDC) = 0;
virtual void DrawScale(CDC* pDC) = 0;
virtual CPoint CalcOnePoint(double fXVal,
double fYVal) = 0;//坐標轉換
該模塊用于讀取跡線上的數(shù)值。包括光標狀態(tài)及位置的設置、光標位置的繪制、光標信息的繪制,封裝為CMarker類。為支持多個光標,定義CMarkerManager類對一組光標進行管理。由CGraph類集合CMarkerManager類的成員變量,并由CGraph調(diào)用CMarkerManager相應接口實現(xiàn)光標功能。
2.2.1CGraph提供的光標功能配置接口
(1) 設置光標顯示狀態(tài)void ShowMkr(UINT nMkrID,BOOL bOn);
(2) 設置光標位置void SetMkrPos(UINT nMkrID,UINT nPos);
(3) 光標信息接口void SetMkrInfoInterface(CMkrInfoInterface* pInf);
由于光標信息的格式是因項目而異,因此定義通用的光標信息接口,由CGraph的使用者進行實現(xiàn),并配置給CGraph。繪圖模塊在繪置光標信息時,調(diào)用該接口,以獲得要顯示的光標信息。
CMrkInfoInterface定義接口:
void GetMkrInfo(
UINT nMkrID, //光標ID
UINT nMkrPos,//光標位置
double data[2], //數(shù)值
int nTraId, //跡線ID
CStringArray& infoAry, //光標信息
CWordArray& widthAry//光標信息區(qū)域劃分
);
2.2.2CMarkerManager類設計
該類定義一組的光標類CMarker成員變量,并提供對指定光標進行設置的接口。
CMarkerManager定義成員變量:
static enum {MKR_NUM = 6};//光標個數(shù)
CTrace* m_pTrace; //關聯(lián)跡線
CMarker m_mkrs[MKR_NUM]; //光標
CMkrInfoInterface* m_pInfoInf;// 光標信息接口
CMarkerManager提供的接口主要有:
void DrawMkrs(CDC* pDC);
void DrawMkrsInfo(CDC* pDC,CRect& rect);
void AssociateToTrace(CGTrace* pTrace);
void SetMkrInfoInterface(CMkrInfoInterface* pInf);
2.2.3CMarker類設計
該類實現(xiàn)對單個光標位置、狀態(tài)、繪制的封裝。
CMarker類定義成員變量:
BOOL m_bOn;//光標狀態(tài)
UINT m_nPos;//光標位置
CMarker類提供的接口主要有:
void DrawMkr(CDC* pDC,CPoint pt);
void DrawMkrInfo(CDC* pDC,
CArray
CStringArray& strInfo);
void SetPos(UINT nDataIdx);
該模塊用于配制繪圖區(qū)頂部和底部的顯示信息。由CGraph類實現(xiàn)信息區(qū)的劃分,通過位置索引的方式來確定顯示的位置,在CGraph類中實現(xiàn)對該信息的繪制。
定義結構體對信息內(nèi)容和位置進行綁定:
typedef struct _XGraphInfo
{
CString strText; //信息區(qū)顯示內(nèi)空
UINT nRowIdx; //信息區(qū)位置橫向索引
UINT nColumIdx;//信息區(qū)位置縱向索引
}XGraphInfo;
在CGraph類中,定義下列成員變量存放頂部和底部信息區(qū)劃分:
UINT m_nTopInfoRowNum;
UINT m_nTopInfoColumNum;
UINT m_nBtmInfoColumNum;
UINT m_nBtmInfoColumNum;
在CGraph類中,定義下列成員變量存放頂部和底部信息配置:
CArray
CArray
在CGraph類中,定義下列接口進行信息區(qū)相應的配置:
void DivideTopInfoZone(UINT nRow,
UINT nColum);//劃分頂部信息區(qū)
void DivideBottomInfoZone(UINT nRow,
UINT nColum);//劃分底部信息區(qū)
void SetTopInfo(UINT nRowIdx,
UINT nColumIdx,CString str);//設置頂部信息
void SetBottomInfo(UINT nRowIdx,
UINT nColumIdx,CString str);//設置底部信息
繪圖模塊以繪圖組件化擴展的方式來支持使用者在繪圖區(qū)自繪制圖形。在Graph中定義隊列成員變量,對繪圖組件的指針進行存儲:
CList< CGComponentInf *, CGComponentInf *> m_pComponentList;
2.4.1CGraph提供的繪圖組件配置接口
void AddComponent(
CGComponentInf* pGComponent);//添加組件
void RemoveComponent(
CGComponentInf* pGComponent);//刪除組件
2.4.2繪圖信息接口類CGInfoInf
繪圖組件需要知道繪圖區(qū)域劃分情況,因此定義繪圖信息接口類,提供以下接口:
virtual CRect GetGridRect()=0;//獲取網(wǎng)格區(qū)
virtual CRect GetGraphRect()=0;//獲取整個繪圖區(qū)
virtual CPoint CalcGraphPoint(double fXValue,
double fYValue) = 0;//數(shù)值轉換為繪圖點
這些由CGraph實現(xiàn),并將指針賦給繪圖組件。
2.4.3繪圖組件接口類CGComponentInf
為了支持在基本繪圖不同縱向位置進行繪制,將基本繪圖分為背景層、網(wǎng)格層、跡線繪制層。繪圖組件接口類提供不同在繪圖層中進行繪制的接口:
virtual void DrawUponBk(CDC* pDC,
CGInfoInf* pGInfo);//在背景層之上繪制
virtual void DrawUponTrace(CDC* pDC,
CGInfoInf* pGInfo);//在跡線層以上繪制
virtual void DrawUponGrid(CDC* pDC,
CGInfoInf* pGInfo);//在網(wǎng)格層之上繪制
以上接口由派生類實現(xiàn),在CGraph中調(diào)用以實現(xiàn)組件繪圖。
對于使用該模塊進行開發(fā)的用戶而言,無需知道上述主要類的實現(xiàn),只需知道CGraphInterface、CGComponentInf的定義。但模塊需對外提供CGraph類對象的創(chuàng)建函數(shù),該函數(shù)返回CGraphInterface類型指針。因此,在工程中新建GraphDll.h、GraphDll.cpp,在GraphDll.h中定義該輸出函數(shù),在GraphDll.cpp中實現(xiàn)該函數(shù)。
該繪圖模塊已應用在某微波綜合測量儀器中,該類型儀器含有:矢量網(wǎng)絡分析儀器、頻譜儀、矢量電壓計、功率計等多種儀表,透過使用該模塊的基本繪圖功能和組件化繪圖擴展方式,成功地滿足了該項目的繪圖需求。如圖2-圖4所示,證明該模塊具有較好的通用性。
圖2 使用基本繪圖功能繪制跡線
圖3 使用繪圖組件實現(xiàn)參數(shù)設置標簽繪制
圖4 使用繪圖組件實現(xiàn)不同繪圖層的繪制
本文設計了一種應用于電子測量儀器領域的通用繪圖模塊,給出模塊的總體設計,各功能模塊的數(shù)據(jù)結構以及接口設計。該繪圖模塊可實現(xiàn)基本的曲線繪制功能,支持以繪圖組件的方式進行實現(xiàn)自定義繪圖。經(jīng)過測試, 表明具有易維護、通用性強等優(yōu)點, 可滿足電子測量儀器的圖形繪制需求。
[1] 楊樂,王厚軍,戴志堅.測試儀器中的動態(tài)波形繪制技術[J].儀器儀表學報,2006,27(S2):1159-1160.
[2] 王澤,朱金偉,曲政.基于COM技術的通用繪圖模塊的構建[J].計算機與數(shù)字工程,2006,34(8):158-160.
[3] 王湘文,陳建倫,陳紀銘.分層軟件架構設計及其應用研究[J].福建電腦,2011,27(6):55-56.
[4] 高松,牛治永.敏捷設計原則與設計模式的編程實踐——單一職責原則與依賴倒置原則[J].計算機應用,2011,31(S2):149-152.
[5] 郭榮.淺談軟件設計模式中的設計原則[J].信息安全與技術,2015(11):5-6.
[6] 王強,湯小慷,謝存,等.基于GDI與雙緩沖技術的雷達PPI顯示器的仿真[J].科技視界,2016(12):123-123.
[7] 周宇,張立群.面向對象技術的多態(tài)性研究[J].電腦與信息技術,2006,14(6):16-19.
[8] 李明明,管志偉.淺析C++多態(tài)的作用及實現(xiàn)原理[J].無線互聯(lián)科技,2014(7):116-116.