自己做一個SymbolSelector

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),爲其他開發者節省時間。

 
發佈了34 篇原創文章 · 獲贊 9 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章