1 Introduction
在AO下不用我說,大家都會調用ISymbolSelector,那麼怎樣在AE 下做一個SymbolSelector。在網上搜了一圈(包括Support.ESRI.com),並沒有太多相關的解決方法,看來只有自力更生了。(某教練說:只要認真去做,中國人沒有做不到的事情)
2 First Method
可以採用ISymbol.SetupDC到PictureBox,將Symbol畫到PictureBox就OK了,這個也是最常用的方法,估計也是ESRI想讓開發者這麼做的。(原因1.ESRI暴露了這方面的接口;原因2.ESRI提供了相關的例子)
這種方法在VB6下應該是比較容易做的,如果你在VB6下開發推薦採用這種方法。但到了.NET反而不好實現了,.NET希望你通過System.Drawing.Graphics去畫東西,另外.NET中的PictureBox控件並沒有暴露hDC(純屬個人猜測,有待大家檢驗)
另外這種方法有一個缺陷:就是如何讓用戶在PictureBox控件中選擇Symbol,這個實現起來就困難了,需要你去判斷Mouse的位置了。
3 Second Method
第二種方法也是今天想拿出來與大家交流的方法:就是依舊選擇在MapControl中畫,也是說你在SymbolSelect對話框中使用MapControl代替PictureBox。這種方法不存在選擇Symbol的問題,對於開發者來說在MapControl選擇Symbol,應該是小菜了。另外在MapControl畫Symbol也不需要我多說了。
但是這種方法也有一個問題,等大家實現了,就可以發現其實畫在MapControl上的效果不是很好,因爲當你有滾動條時,上滾下滾都導致MapControl的刷新,但是刷新Symbol的效果讓人十分鬱悶。(目前至少我實現後的效果出現了刷新的問題,如果你有好方法請告知。)
下面就實現最關鍵的部分,其實代碼是很簡單,要提出的是這裏使用的接口都是基於AE的,請放心。尤其要提起的是ServerStyleGallery對應的是以.ServerStyle爲後綴名的Style文件(如ESRI.ServerStyle)
Private Sub DrawSymbols()
If CurSymbol Is Nothing Then Exit Sub
Dim pGC As IGraphicsContainer = SymbolMap.Map
Dim pStyleGlry As IStyleGallery
pStyleGlry = New ServerStyleGallery
Dim pStylePath As String 'Add the Civic.style to the IStyleGalleryStorage
Dim pStylStor As IStyleGalleryStorage
pStylStor = pStyleGlry
''ServerStyle Path
pStylePath = My.Application.Info.DirectoryPath & "/Style/ESRI.ServerStyle"
pStylStor.AddFile(pStylePath) 'Locate the first fill
Dim pItems As IEnumStyleGalleryItem = Nothing
If TypeOf CurSymbol Is IFillSymbol Then
pItems = pStyleGlry.Items("Fill Symbols", pStylePath, "Default")
''如果是Fill Symbols,畫RectangleElement
DrawPolygon(pGC, pItems)
ElseIf TypeOf CurSymbol Is IMarkerSymbol Then
pItems = pStyleGlry.Items("Marker Symbols", pStylePath, "Default")
''如果是Marker Symbols,畫MarkerElement
DrawPoint(pGC, pItems)
ElseIf TypeOf CurSymbol Is ILineSymbol Then
pItems = pStyleGlry.Items("Line Symbols", pStylePath, "Default")
''如果是Marker Symbols,畫LineElement
DrawLine(pGC, pItems)
Else
Exit Sub
End If
Dim env As IEnvelope = New Envelope
env.XMin = 0
env.YMin = 0
env.XMax = 310
env.YMax = 300
SymbolMap.ActiveView.Extent = env
SymbolMap.ActiveView.Refresh()
End Sub
''' <summary>
''' 如果是Fill Symbols,畫RectangleElement
''' </summary>
''' <param name="pGC"></param>
''' <param name="pItems"></param>
''' <remarks></remarks>
Private Sub DrawPolygon(ByVal pGC As IGraphicsContainer, ByVal pItems As IEnumStyleGalleryItem)
Dim pItem As IStyleGalleryItem
pItem = pItems.Next
Dim i As Integer = 0
Dim j As Integer = 0
While pItem IsNot Nothing
Dim pPolygon As IPolygon = New Polygon
Dim pPC As IPointCollection = pPolygon
Dim ii As Integer = i / 6
Dim p1 As IPoint = New Point
p1.X = 10 + j * 50
p1.Y = 10 + ii * 50
pPC.AddPoint(p1)
Dim p2 As IPoint = New Point
p2.X = 10 + j * 50
p2.Y = 50 + ii * 50
pPC.AddPoint(p2)
Dim p3 As IPoint = New Point
p3.X = 50 + j * 50
p3.Y = 50 + ii * 50
pPC.AddPoint(p3)
Dim p4 As IPoint = New Point
p4.X = 50 + j * 50
p4.Y = 10 + ii * 50
pPC.AddPoint(p4)
Dim pE As IElement = New RectangleElement
pE.Geometry = pPolygon
Dim pFSE As IFillShapeElement = pE
pFSE.Symbol = pItem.Item
pgc.AddElement(pE, 0)
pItem = pItems.Next
i = i + 1
''逢六換行
j = (j + 1) Mod 6
End While
End Sub
''' <summary>
''' 如果是Marker Symbols,畫LineElement
''' </summary>
''' <param name="pGC"></param>
''' <param name="pItems"></param>
''' <remarks></remarks>
Private Sub DrawLine(ByVal pGC As IGraphicsContainer, ByVal pItems As IEnumStyleGalleryItem)
Dim pItem As IStyleGalleryItem
pItem = pItems.Next
Dim i As Integer = 0
Dim j As Integer = 0
While pItem IsNot Nothing
Dim pPolyline As IPolyline = New Polyline
Dim pPC As IPointCollection = pPolyline
Dim ii As Integer = i / 6
Dim p1 As IPoint = New Point
p1.X = 10 + j * 50
p1.Y = 30 + ii * 50
pPC.AddPoint(p1)
Dim p2 As IPoint = New Point
p2.X = 50 + j * 50
p2.Y = 30 + ii * 50
pPC.AddPoint(p2)
Dim pE As IElement = New LineElement
pE.Geometry = pPolyline
Dim pLE As ILineElement = pE
pLE.Symbol = pItem.Item
pGC.AddElement(pE, 0)
pItem = pItems.Next
i = i + 1
''逢六換行
j = (j + 1) Mod 6
End While
End Sub
''' <summary>
''' 如果是Marker Symbols,畫MarkerElement
''' </summary>
''' <param name="pGC"></param>
''' <param name="pItems"></param>
''' <remarks></remarks>
Private Sub DrawPoint(ByVal pGC As IGraphicsContainer, ByVal pItems As IEnumStyleGalleryItem)
Dim pItem As IStyleGalleryItem
pItem = pItems.Next
Dim i As Integer = 0
Dim j As Integer = 0
While pItem IsNot Nothing
Dim ii As Integer = i / 6
Dim p1 As IPoint = New Point
p1.X = 30 + j * 50
p1.Y = 30 + ii * 50
Dim pE As IElement = New MarkerElement
pE.Geometry = p1
Dim pME As IMarkerElement = pE
pME.Symbol = pItem.Item
pGC.AddElement(pE, 0)
pItem = pItems.Next
i = i + 1
''逢六換行
j = (j + 1) Mod 6
End While
End Sub
4 End
以上都是個人的觀點,存在一定的錯誤和不確定,請大家指正。另外實現SymbolSelect對話框也不只這兩種方法,說不定大家已經有好的方法,沒拿出來分享而已,希望大家能貢獻一些源碼(Open Source),爲其他開發者節省時間。