5

I have the following situation in an ArcMap add-in that I'm building:

This add-in contains a form where a user needs to click on a button, and then be able to draw a polyline on the map (the form is non-modal). The polyline is needed in the form for further processing.

I have now implemented this using a tool that inherits from ESRI.ArcGIS.Desktop.AddIns.Tool, and uses a RubberLineClass in the OnMouseDown event. The tool is activated in the button's OnClick event. This all works, and the user can draw the polyline.

The problem is getting the polyline from the tool. I was thinking to have the tool add the polyline as a graphic element to the map, and in the form listen to the ItemAdded event on IActiveView. Unfortunately, this event is only raised when maplayers are added. It does work with elements on the PageLayout, but if I add the element to that, the polyline's coordinates are altered. Also, this feels a bit clumsy.

So, the question is: Is there a better way to get information from a tool? Or is there a way to draw a polyline on the map without using a tool?

Maybe not relevant, but here's the code anyway:

// Activate the tool
var documentBars = ((IDocument)ArcMap.Document).CommandBars;
var cmdItem = documentBars.Find(new UIDClass { Value = ThisAddIn.IDs.PolylineTool });
ArcMap.Application.CurrentTool = cmdItem;

// The tool's OnMouseDown event
protected override void OnMouseDown(MouseEventArgs arg)
{
    var rubberBand = new RubberLineClass();
    var geometry = rubberBand.TrackNew(ArcMap.Document.ActiveView.ScreenDisplay, new SimpleLineSymbolClass { Color = new RgbColorClass { Red = 255 } });
    geometry.SpatialReference = ArcMap.Document.FocusMap.SpatialReference;

    if (!geometry.IsEmpty)
    {
        var container = (IGraphicsContainer)ArcMap.Document.FocusMap;
        container.AddElement(new LineElementClass { Geometry = geometry }, 0);
    }
}
  • 1
    In some situations I've found it easier to change the use-case: User draws a polyline graphic using out-of-the-box tool. User selects graphic. User clicks custom button. System verifies that one polyline graphic is selected, and uses it for processing. – Kirk Kuykendall Dec 5 '16 at 18:02
  • @KirkKuykendall Yeah, I considered doing it that way, but it adds extra logic that needs to be handled. E.g. more than one graphic might be on the map, a user needs to remove the graphic afterwards. – Berend Dec 6 '16 at 9:27
5

Just looked at some old code and the way I did this is:

  1. My form was actually a dockable window, not sure that makes a difference?
  2. In the New() event of the window I get a handle on the tool and then add an event handle:
        ' Get a handle on tool control and listener for event
        m_tool = ESRI.ArcGIS.Desktop.AddIns.AddIn.FromID(Of HER_AddIn.btnGetHERID)("GDI_HER_AddIn_btnGetHERID")
        AddHandler m_tool.HERIDGrabbed, AddressOf captureHERID
  1. In the dockable window is a private sub that deals with the event, in may case captureHERID. The first thing this sub does is get the point geometry from a publicly exposed property I had created for the tool.
pPoint = m_tool.OnPointClicked
  1. My code for the tool is as below:
Imports ESRI.ArcGIS.Geometry
Imports ESRI.ArcGIS.ArcMapUI
Imports ESRI.ArcGIS.Display

Public Class btnGetHERID
    Inherits ESRI.ArcGIS.Desktop.AddIns.Tool

    ''' <summary>Declare an Event called HERIDGrabbed</summary>
    ''' <remarks>This is the event that is listened out for in the dkwEditHER window</remarks>
    Public Event HERIDGrabbed()

    ''' <summary>The coordinate of the location clicked by the user.</summary>
    ''' <remarks>The XY coordinates are in map units.</remarks>
    Private m_Point As IPoint

    Public Sub New()
        ' Initialise point object and set to a default 0,0 location
        m_Point = New PointClass
        m_Point.PutCoords(0, 0)
    End Sub

    Protected Overrides Sub Finalize()
        m_Point = Nothing
        MyBase.Finalize()
    End Sub

    ''' <summary>Enables tool.</summary>
    ''' <remarks>This tool is always available but does not exist on any toolbar.</remarks>
    Protected Overrides Sub OnUpdate()
        Me.Enabled = True
    End Sub

    ''' <summary>Captures location clicked in map units.</summary>
    ''' <param name="arg">MouseEventAgs</param>
    ''' <remarks>Raises the event HERIDGrabbed</remarks>
    Protected Overrides Sub OnMouseDown(arg As ESRI.ArcGIS.Desktop.AddIns.Tool.MouseEventArgs)

        ' Convert location clicked into real world map units and store
        Dim pMXdocument As IMxDocument
        pMXdocument = My.ArcMap.Document
        Dim pScreenDisplay As IScreenDisplay
        pScreenDisplay = pMXdocument.ActiveView.ScreenDisplay
        m_Point = pScreenDisplay.DisplayTransformation.ToMapPoint(arg.X, arg.Y)

        ' Raise the event
        RaiseEvent HERIDGrabbed()
        MyBase.OnMouseDown(arg)
    End Sub

    ''' <summary>A public function that returns the location clicked.</summary>
    ''' <returns>An IPoint object</returns>
    ''' <remarks>During initialization this is set to 0,0 so the return point is always a valid point object.</remarks>
    Public Function OnPointClicked() As IPoint
        OnPointClicked = m_Point
    End Function

End Class

Make sure you remove the event handler from the form when you close it.

  • Great, I didn't know the FromID() method – Berend Dec 6 '16 at 9:20
1

I think a simpler approach is to create the geometry using the INewLineFeedback interface. The stop method returns the shape. Much easier that implementing a bunch of event handlers. You should be able to implement this in your tool.

Alternatively, use one of the out-of-box selection tools (line, rectangle, polygon) to draw the shape but rather than create a selection just grab the shape. Here is an Esri sample: Custom selection extension

It's probably best to grab the shape from the OnDoubleClick event in your custom tool and do what you need with it. There are similar interfaces for the other geometry types.

Also related: Get the geometry from the lasso selection tool

  • That seems to just replace the Rubberband class, am I right? I would still need a custom tool to grab the mousedown event. – Berend Dec 8 '16 at 9:11
  • Yeah, I don't think I understood your problem. Thought you were having trouble acquiring the shape from a custom tool. If you have a reference to the shape from the tool you implemented then what is the issue? It's up to you whether to draw it on the map or not but if you have the shape then just pass it along to the rest of the program from the mouse down event. – Rich Wawrzonek Dec 8 '16 at 22:59
  • The problem was how to reference the geometry in a custom form (i.e. another class than the tool). Hornbydd gave the answer to that. – Berend Dec 12 '16 at 8:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.