arcgis engine 监听element的添加、更新和删除事件(使用IMovePointFeedback)

本文提供了一段VB代码示例,展示了如何创建一个工具,允许用户在ArcMap中通过适当的反馈接口移动各种几何类型(标记、线、矩形、多边形)。该工具通过鼠标操作实现图形的选择和移动。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VB代码:
复制进程序稍作修改变量名和事件逻辑即可使用。
Members
 AllPropertiesMethodsInheritedNon-inheritedDescription
Write-on<wbr>ly propertyDisplayThe display the feedback object will use.
MethodMoveToMove to the new point.
MethodRefreshCall this after a refresh to show feedback again.
MethodStartBegins a move feedback of the given shape.
MethodStopStops the feedback and returns the shape.
Read/write propertySymbolThe symbol the feedback object will use.

Moving Feedbacks Example
This example shows how to create a tool which allows the user to move various geometry types using the appropriate feedback interfaces. The example requires there to be at least one of the following in the current document's BasicGraphicsLayer: MarkerElement, LineElement, RectangleElement, or PolygonElement. When the mouse button is pressed a search is made for any elements which intersect the mouse location. If any are found, then the first of these is taken. If the element's geometry is a Point, Polyline, Envelope or Polygon, then a Feedback object of that type is created, otherwise nothing is created and the routine will exit. Once the feedback has been created, any subsequent mouse movements cause this feedback to be moved on the screen. Releasing the mouse button will stop the feedback and update the element with the new geometry. The ActiveView is then refreshed.
 
How to use:
In ArcMap, select Tools | Customize... 
Select the Commands tab and scroll down to UIControls in the left pane. 
Click NewUIControl... 
In the dialog which appears select UIToolControl and then click Create. 
Drag the new tool which appears in the right pane onto a toolbar of your choosing. 
Right-click over your tool on the toolbar and select View Source. 
Copy and paste the code below into the VBA code pane which appears. 
Close the VBA Window and return to the ArcMap Window. 
Now select your tool from the toolbar and click on a graphic element (Marker, Line, Rectangle, Polygon) and move the mouse until the desired location is reached. Releasing the mouse button to finish. 
Private m_pDoc As IMxDocument

Private m_pAV As IActiveView

Private m_pScrD As IScreenDisplay

Private m_pDispFeed As IDisplayFeedback

Private m_pHitElem As IElement

Private m_pGraCont As IGraphicsContainer

 

Private Function UIToolControl1_Enabled() As Boolean

  'Set the ToolControl to enabled (disabled by default)

  UIToolControl1_Enabled = True

End Function

 

Private Sub UIToolControl1_MouseDown(ByVal button As Long, ByVal shift As Long, ByVal x As Long, ByVal y As Long)

  Dim pPnt As IPoint

  Dim pGeomElem As IGeometry

  

  ' Get the current mouse location in Map Units

  Set pPnt = m_pScrD.DisplayTransformation.ToMapPoint(x, y)

  ' Use a function to return the first element at this point (if any)

  Set m_pHitElem = GetHitElement(pPnt)

  

  ' If an element was returned then check what type of geometry it has (Point, Polyline, Envelope or Polygon)

  If Not m_pHitElem Is Nothing Then

    Set pGeomElem = m_pHitElem.Geometry

    'Point geometry

    If TypeOf pGeomElem Is IPoint Then

      ' Create a MovePointFeedback object and set its display property (to the ActiveView's ScreenDisplay)

      Set m_pDispFeed = New MovePointFeedback

      Set m_pDispFeed.Display = m_pScrD

      ' QI for the IMovePointFeedback interface

      Dim pMvPtFeed As IMovePointFeedback

      Set pMvPtFeed = m_pDispFeed

      'Start the feedback using the input (Point) geometry at the current mouse location

      pMvPtFeed.Start pGeomElem, pPnt

  

    ' Polyline geometry

    ElseIf TypeOf pGeomElem Is esriCore.IPolyline Then

      ' Create a MoveLineFeedback object and set its display property (to the ActiveView's ScreenDisplay)

      Set m_pDispFeed = New MoveLineFeedback

      Set m_pDispFeed.Display = m_pScrD

      ' QI for the IMoveLineFeedback interface

      Dim pMvLnFeed As IMoveLineFeedback

      Set pMvLnFeed = m_pDispFeed

      'Start the feedback using the input (Polyline) geometry at the current mouse location

      pMvLnFeed.Start pGeomElem, pPnt

    

    ' Rectangle (Envelope) geometry

    ElseIf TypeOf pGeomElem Is IEnvelope Then

      ' Create a MoveEnvelopeFeedback object and set its display property (to the ActiveView's ScreenDisplay)

      Set m_pDispFeed = New MoveEnvelopeFeedback

      Set m_pDispFeed.Display = m_pScrD

      ' QI for the IMoveEnvelopeFeedback interface

      Dim pMvEnvFeed As IMoveEnvelopeFeedback

      Set pMvEnvFeed = m_pDispFeed

      'Start the feedback using the input (Rectangle) geometry at the current mouse location

      pMvEnvFeed.Start pGeomElem, pPnt

    

    ' Polygon geometry

    ElseIf TypeOf pGeomElem Is IPolygon Then

      ' Create a MovePolygonFeedback object and set its display property (to the ActiveView's ScreenDisplay)

      Set m_pDispFeed = New MovePolygonFeedback

      Set m_pDispFeed.Display = m_pScrD

      ' QI for the IMovePolygonFeedback interface

      Dim pMvPolyFeed As IMovePolygonFeedback

      Set pMvPolyFeed = m_pDispFeed

      'Start the feedback using the input (Polygon) geometry at the current mouse location

      pMvPolyFeed.Start pGeomElem, pPnt

    End If

  End If

End Sub

 

Private Sub UIToolControl1_MouseMove(ByVal button As Long, ByVal shift As Long, ByVal x As Long, ByVal y As Long)

  If Not m_pDispFeed Is Nothing Then

    

    Dim pPnt As IPoint

    ' Get the current mouse location in Map Units and move the feedback

    Set pPnt = m_pScrD.DisplayTransformation.ToMapPoint(x, y)

    m_pDispFeed.MoveTo pPnt

  End If

End Sub

 

Private Sub UIToolControl1_MouseUp(ByVal button As Long, ByVal shift As Long, ByVal x As Long, ByVal y As Long)

  Dim GeomResult As IGeometry

  Dim pGeomElem As IGeometry

  

  ' Check that the user is using the feedback

  If Not m_pHitElem Is Nothing Then

    ' Get the geometry type for our element again

    Set pGeomElem = m_pHitElem.Geometry

    

    ' Check what type of geometry the element has  (again)

    ' Point geometry

    If TypeOf pGeomElem Is IPoint Then

      ' QI for the IMovePointFeedback interface and get the finished geometry

      Dim pMvPtFeed As IMovePointFeedback

      Set pMvPtFeed = m_pDispFeed

      Set GeomResult = pMvPtFeed.Stop

    ElseIf TypeOf pGeomElem Is IPolyline Then

      ' QI for the IMoveLineFeedback interface and get the finished geometry

      Dim pMvLnFeed As IMoveLineFeedback

      Set pMvLnFeed = m_pDispFeed

      Set GeomResult = pMvLnFeed.Stop

    ElseIf TypeOf pGeomElem Is IEnvelope Then

      ' QI for the IMoveEnvelopeFeedback interface and get the finished geometry

      Dim pMvEnvFeed As IMoveEnvelopeFeedback

      Set pMvEnvFeed = m_pDispFeed

      Set GeomResult = pMvEnvFeed.Stop

      

    ElseIf TypeOf pGeomElem Is IPolygon Then

      ' QI for the IMovePolygonFeedback interface and get the finished geometry

      Dim pMvPolyFeed As IMovePolygonFeedback

      Set pMvPolyFeed = m_pDispFeed

      Set GeomResult = pMvPolyFeed.Stop

        

    End If

  

    ' Set the geometry of the element and call update

    m_pHitElem.Geometry = GeomResult

    m_pGraCont.UpdateElement m_pHitElem

    

    ' Clear out the objects

    Set m_pDispFeed = Nothing

    Set m_pHitElem = Nothing

    

    ' Refresh the ActiveView

    m_pAV.Refresh

  End If

End Sub

 

Private Sub UIToolControl1_Refresh(ByVal hDC As Long)

  'Get a reference to the ActiveView and ScreenDisplay

  Set m_pDoc = Application.Document

  Set m_pAV = m_pDoc.ActiveView

  Set m_pScrD = m_pAV.ScreenDisplay

End Sub

 

Private Sub UIToolControl1_Select()

  'Get a reference to the ActiveView and ScreenDisplay

  Set m_pDoc = Application.Document

  Set m_pAV = m_pDoc.ActiveView

  Set m_pScrD = m_pAV.ScreenDisplay

End Sub

 

Private Function GetHitElement(pInPt As IPoint) As IElement

' Takes an IPoint and returns the first element that is hit (if any) in the ActiveView's BasicGraphicsLayer

  Dim pEnumElem As IEnumElement

  Dim DblSrchDis As Double

  

  ' QI for the IGraphicsContainer interface from the IActiveView, allows access to the BasicGraphicsLayer

  Set m_pGraCont = m_pAV

  

  ' Calculate the Search Distance (in MapUnits) based upon a portion of the ActiveView's width

  DblSrchDis = m_pAV.Extent.Width / 200

  

  ' Return an enumerator for those elements found within the search distance (in mapunits)

  Set pEnumElem = m_pGraCont.LocateElements(pInPt, DblSrchDis)

  

  ' If the enumerator is not empty then return the FIRST element found

  If Not pEnumElem Is Nothing Then

    Set GetHitElement = pEnumElem.Next

  End If

 

End Function

 

客户最近打电话过来,说我们的软件在量距离的时候不能平移地图。我们的软件是使用ArcEngine来开发的,在网上输入关键字“arcengine 距离测量”,可以搜索到一大堆内容基本相似的文章或代码,基本上都是采用INewLineFeedback来实现的,我们的软件也是使用此种方法。方法大致如下:写一个距离测量工具,继承自BaseTool,在该类中使用INewLineFeedback动态绘制多段折线,最后转化为Element添加到地图上。如果要增加平移功能,我们仿造ArcMap使用鼠标中键平移,在OnMouseDown、OnMouseMove、OnMouseUp事件中增加判断鼠标中键的语句,然后分别使用PanStart、PanMoveTo、PanStop实现地图的平移。 此时,出现了一个新问题,一旦移动地图后,之前使用INewLineFeedback绘制的线完全乱了方寸,有一部分线丢失了。之后又发现一个更可笑的问题,在绘制的过程中,如果使用alt+tab键切换到其它窗口,然后再切换回地图窗口的时候,会多出一条线,INewLineFeedback把切换窗口前的鼠标位置记录了下来。 对于这个问题,我使用ArcMap的测量工具检查了一下,发现不存在上述问题。但是INewLineFeedback为什么会产生这个bug,难道是本人的使用方法不对。在网上搜了一下其他类似代码进行测试,都存在这个bug。ArcEngine的SDK文档上也没有特别强调INewLineFeedback的使用细节。 本来打算用gdi进行解决,最后发现INewLineFeedback有一个Refresh函数,那么应该在什么地方使用它呢?在ArcMapControl的诸多事件中,尝试了OnAfterDraw、OnAfterScreenDraw、OnViewRefresh等,发现OnAfterScreenDraw是OK的。具体是在OnAfterScreenDraw事件使用Refresh函数刷新INewLineFeedback,完美解决问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值