MO開(kāi)發(fā)小技巧(二)-- 符號(hào)化
這一篇講一下如何通過(guò)MO實(shí)現(xiàn)符號(hào)化,請(qǐng)多多指教
一、先看一下鄙人完成的程序的界面:
圖一、符號(hào)化(專(zhuān)題圖Thematic)設(shè)置界面
圖二、面狀符號(hào)選擇面板
圖三、 線狀符號(hào)選擇面板
可以看到,整個(gè)符號(hào)化界面是模仿ArcView 來(lái)完成的。
二、符號(hào)化實(shí)現(xiàn)的基本思路
實(shí)現(xiàn)符號(hào)化的思路很多,下面介紹一下本人實(shí)現(xiàn)的思路。 〕
1、點(diǎn)狀符號(hào)化:采用字體來(lái)完成即可。
制作字體的方法:建議采用CoralDraw完成。
2、線狀符號(hào)化:
打開(kāi)MO自帶的例子CustomSym,先仔細(xì)看一下代碼,搞清楚其實(shí)現(xiàn)的思路。
MO在符號(hào)化方面提供了一個(gè)接口叫ICustom,該接口有三個(gè)需要實(shí)現(xiàn)的接口函數(shù):SetupDC,Draw和ResetDC。很容易理解,三個(gè)函數(shù)分別實(shí)現(xiàn)以下功能:
SetupDC: 熟悉GDI編程的朋友都知道,Windows界面中所看到的一切都是通過(guò)函數(shù)(本質(zhì)是都是調(diào)API)繪制在一個(gè)DC上的。DC就相當(dāng)于作畫(huà)的畫(huà)布。SetupDC的作用就是在作畫(huà)之前先作好準(zhǔn)備工作。這些準(zhǔn)備工作包括繪制的畫(huà)筆(Pen)或畫(huà)刷(Brush),以及畫(huà)布的相關(guān)信息。
該函數(shù)的原型是:Public Sub SetupDC(hdc As Long, dpi As Double, baseSym As Object)
其中hdc就是畫(huà)布的句柄,dpi為畫(huà)布的分辨率,baseSym是一個(gè)Symbol對(duì)象,定義了畫(huà)筆的風(fēng)格,如Symbol.Color為畫(huà)筆的顏色,Symbol.Size為畫(huà)筆的寬度。當(dāng)然只要你愿意,也可以不用它,在這里,完全可以自由發(fā)揮。
Draw:到了真正繪制的時(shí)候了,這個(gè)函數(shù)中的代碼,決定了整個(gè)符號(hào)化所表現(xiàn)出來(lái)的效果。
該函數(shù)的原型是:Public Sub Draw(hdc As Long, points As Long, partCounts As Long, numParts As Long)
該函數(shù)有四個(gè)參數(shù),第一個(gè)同樣是畫(huà)布的句柄,后面三個(gè)定義了要繪制的數(shù)據(jù)。其中points函數(shù)給出了所有要繪制的線的組成點(diǎn)的集合的首地址;partcount也是指向了一個(gè)數(shù)組,它定義了每一條線的點(diǎn)的個(gè)數(shù); numParts告訴我們這么多點(diǎn)是由多少了斷開(kāi)的線所組成。細(xì)心的朋友會(huì)發(fā)現(xiàn),這三個(gè)參數(shù)與一個(gè)API函數(shù)Polypolyline的參數(shù)如出一轍! 確實(shí)如此,如果我們?cè)诙x的畫(huà)筆之后,直接調(diào)用polypolyline(points,partCounts,numParts),執(zhí)行,你會(huì)發(fā)現(xiàn)數(shù)據(jù)的顯示已經(jīng)變成了你所定義的樣式。這本身提供了一種符號(hào)化的方法,即定義畫(huà)筆的方式。該方法實(shí)現(xiàn)思路簡(jiǎn)單,運(yùn)行速度快,但難以做到隨心所欲的繪制,很難完全滿足現(xiàn)實(shí)需要。
在CustomSym例子中,用到了一個(gè)庫(kù)叫mohelper,其功能是將參數(shù)中給出的點(diǎn)集得新組合整理,變成一個(gè)個(gè)實(shí)實(shí)在在線對(duì)象(MultiShape)。有了這些線,繪制就容易多了。
下面看一看例子中給出的Draw函數(shù)的代碼:
Public Sub Draw(hdc As Long, points As Long, partCounts As Long, numParts As Long)
Dim pl As New MoHelper.MultiShape ' new polyline
pl.Init points, partCounts, numParts
Dim l As MoHelper.Shape ' line pointer
Dim i As Long
For i = 0 To numParts - 1
Set l = pl.Part(i) ' point to next line
'Debug.Print "count: " + CStr(i) + ":" + CStr(l.Count)
PolylineL hdc, l.Pointer, l.Count
DrawTies hdc, l
Next i
End Sub
思路很明顯,就是逐條繪制集合中的第一條線。我采用的也是同樣的做法。只不過(guò),為了實(shí)現(xiàn)自定義線型,需要抽象更多的東西,其中最重要的一個(gè)是LineUnit,即繪制單元,下面稱(chēng)為線單元。當(dāng)然,這也是建立在一個(gè)假設(shè)之上,即所有的線型都是以某一長(zhǎng)度的單元作為模板重復(fù)繪制的(事實(shí)上不一定如此,但很少,對(duì)于這種情況,可以單獨(dú)出來(lái)考慮)。所以要實(shí)現(xiàn)繪制功能,第一步就是將一條線按長(zhǎng)度劃分成若干個(gè)單元,這個(gè)工作并不復(fù)雜。事實(shí)上,在CustomSym例子中DrawTies函數(shù)已經(jīng)實(shí)現(xiàn)了這個(gè)功能。
所以現(xiàn)在問(wèn)題的關(guān)鍵變成了如保定義和繪制第一個(gè)線單元。
一個(gè)線單元由若干固定要素構(gòu)成。由于繪制一條線的過(guò)程,就是重復(fù)繪制一個(gè)線單元的過(guò)程,每個(gè)線單元都有一個(gè)“中心線”,它決定了這個(gè)線單元彎曲的形狀和走向。現(xiàn)在假設(shè)我們把這個(gè)中心線拉直,那么這個(gè)線單元中所有要素的相對(duì)位置也是固定不變的。現(xiàn)在我們假設(shè)每個(gè)要素為一個(gè)層,那么一個(gè)線單元就是由多個(gè)相對(duì)位置的層構(gòu)成。由此我們可以設(shè)計(jì)一個(gè)LineUnit類(lèi),用于保存所有這些要素的形狀以及位置信息。在繪制時(shí),再根據(jù)中心線的位置,確定每個(gè)要素的實(shí)際位置。并將其繪制在hdc上。
實(shí)際應(yīng)用中包含多少種要素,怎么樣劃分這些要素,方式多種多樣,請(qǐng)朋友們自己思考完成。
ResetDC函數(shù) :即繪制完畢后,進(jìn)行善后處理工作。主要是進(jìn)行資源清理和狀態(tài)回復(fù)。
函數(shù)原型是:Public Sub ResetDC(hdc As Long)
3、面狀符號(hào)化:
面狀符號(hào)化也是通過(guò)ICustom接口實(shí)現(xiàn)的。
實(shí)現(xiàn)的思路也有很多種。這里只介紹一下本人的實(shí)現(xiàn)方法--采用圖片填充。該方法思路簡(jiǎn)單,實(shí)現(xiàn)方便,速度也很快。圖片如何填充呢?在Windows API編程中,填充采用刷子(Brush)來(lái)進(jìn)行的,而這個(gè)刷子又可以通過(guò)位圖來(lái)定義,這就為面狀符號(hào)化提供了一個(gè)最簡(jiǎn)單的方法。
三、符號(hào)化中碰到的實(shí)際問(wèn)題
1、怎么制符號(hào)庫(kù)
符號(hào)化要實(shí)現(xiàn),必須可以自定義符號(hào),制作自己的符號(hào)庫(kù)。基本思路是以記錄的形式定義符號(hào)的結(jié)構(gòu),然后將這些數(shù)據(jù)依次寫(xiě)入文件中。對(duì)于線狀符號(hào),每條記錄等長(zhǎng),讀寫(xiě)比較方便。對(duì)于面狀符號(hào),由于采用圖片,圖片可能不一樣, 這時(shí),可同時(shí)建立一個(gè)索引文件,記錄每條記錄的長(zhǎng)度以及在文件中的位置,以便于進(jìn)行檢索。
2、面狀填充前景色的背景色的實(shí)現(xiàn)
圖片采用pf1bit格式存儲(chǔ),這樣文件大小非常小,而且圖片只有黑白兩色,這樣在使用前方便進(jìn)行預(yù)處理。可以將黑色的像素處理成前景色,白色的像素處理背景色。
3、將自定義的符號(hào)化顯示到任意畫(huà)布的任意區(qū)域中。
經(jīng)過(guò)上述思路,雖然實(shí)現(xiàn)了符號(hào)化,但怎樣將符號(hào)的樣式顯示在指定的位置,從而實(shí)現(xiàn)符號(hào)面板的制作呢?其實(shí)很簡(jiǎn)單,上面講到,實(shí)現(xiàn)符號(hào)化實(shí)際就是實(shí)現(xiàn)了ICustom接口的三個(gè)函數(shù):SetUpDC,Draw和ResetDC,其實(shí)我們完全可以利用這三個(gè)函數(shù)將符號(hào)顯示在任意區(qū)域。具體方法請(qǐng)朋友們自己思考。
posted on 2005-03-24 17:48 西西吹雪 閱讀(2474) 評(píng)論(1) 收藏 舉報(bào)
浙公網(wǎng)安備 33010602011771號(hào)