Select to view content in your preferred language

C# OnMouseDown returning an IPoint?

6379
18
03-28-2012 11:11 AM
LucieBoucher1
Deactivated User
Hi,

I'm a newbie to developping add-ins in C#, probably mixing many concepts and principles...

I have built a simple tool that gets the coordinates when the user clicks on the map.  For now, I have a GetCoord.cs file with the following code :

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using ESRI.ArcGIS.Geometry; //For geometry IPoint
using ESRI.ArcGIS.Carto; //For ActiveView
using ESRI.ArcGIS.Display; //For IScreenDisplay


namespace myProject
{
    public class GetCoord: ESRI.ArcGIS.Desktop.AddIns.Tool
    {
        public GetCoord()
        {
        }

        protected override void OnUpdate()
        {
        }

        protected override void OnMouseDown(ESRI.ArcGIS.Desktop.AddIns.Tool.MouseEventArgs arg)
        {
            try
            {
                //Get the active view
                IActiveView activeView = ArcMap.Document.ActiveView;
                IScreenDisplay screenDisplay = activeView.ScreenDisplay;

                //Get the point when the user clicks on the map
                IPoint myPoint = screenDisplay.DisplayTransformation.ToMapPoint(arg.X, arg.Y);
                System.Windows.Forms.MessageBox.Show("X coordinate from the IPoint: " + myPoint.X);
                System.Windows.Forms.MessageBox.Show("Y coordinate fom the IPoint: " + myPoint.Y);
            }
            catch (Exception e)
            {
                System.Windows.Forms.MessageBox.Show("Problem to get the coordinates: " + e.Message);
            }
        }
    }
}


This codes works, I have the tool on my toolbar, I click on the tool and then on the map, and the coordinates are written in the message box. 🙂

What I would like to do next is to use this tool within other methods and classes, to use the coordinates for different purposes.  For instance, I would like to create a NewPoint.cs button, which would call the GetCoord.OnMouseDown() function and use the provided coordinates to create a new point in a feature class. 

I was therefore wondering if I could modify my code to get something like this :
public override IPoint OnMouseDown(ESRI.ArcGIS.Desktop.AddIns.Tool.MouseEventArgs arg)
{
    //Get the active view
    IActiveView activeView = ArcMap.Document.ActiveView;
    IScreenDisplay screenDisplay = activeView.ScreenDisplay;
    //Get the point when the user clicks on the map
    IPoint myPoint = screenDisplay.DisplayTransformation.ToMapPoint(arg.X, arg.Y);
    return myPoint;
}


and then, later in another cs file :
Ipoint myNewPoint = GetCoord.OnMouseDown(ESRI.ArcGIS.Desktop.AddIns.Tool.MouseEventArgs arg);


Thank you for your help!
0 Kudos
18 Replies
AlexanderGray
Honored Contributor
There are some different philosophy and reusability.  The advantages a real and it makes sense in some cases but there are disadvantages too.  If the code is only a few lines, the probability of error in the code is low so the fixing it one place fixes all is not always applicable.  There is also the risk of changing one function breaks all the others... 
If your code is crashing ArcMap, you need to put exception handlers in it.  Any event called by ArcMap (ie any implementation of ArcObjects interfaces) should have exception handlers.
0 Kudos
sapnas
by
Frequent Contributor
In fact if it is few lines of code it is always good to reuse it. Imagine repeating those few lines of code in multiple places. Let's say there is custom tool and you want to incorporate that same functionality in another tool bar or standalone application. Would you rewrite it or reuse the existing tool? But then like I said it varies on case by case basis.
0 Kudos
AlexanderGray
Honored Contributor
I would most likely copy/paste the tool so yes two or more copies.  The problem I find is requirements change over time and functions need to be tweaked for various reasons.  If the code is centralized in one function it makes it harder to follow someone else's or my train of though from a long time ago.  I like to keep things simple in one class even if that means more code overall.  It means you can move that class to another project without dragging 5 or 6 utility classes that contain hundreds of methods when you only need one in each...  I just spent a day going through an ArcObjectsUtil class that had 6000 lines of code done by another programmer that is not here any more.  I found out that 70% of the methods weren't called by anything any more.  Meaning that we had almost 4000 lines of code being maintained and cluttering up the project for no good reason.  Some of the code was to convert one type of list to another, 1 line of code with a lambda expression with Framework 3.5...   Reusability is fine but there are specific ways of doing it such has inheritance or class extensions that make it work nicely but you have to think of the poor guy coming after you, is he/she going to be able to make any sense of it...
0 Kudos
sapnas
by
Frequent Contributor
The segment of source code is reused only if it has slight or no modification. You dont consider reusability if the requirement changes significantly and is not common among different parts. Hence I stated it depends on case by case basis.
Regarding your statement about dragging 5 or 6 utilities, when you are utilizing the ESRI APIs they have several classes packaged in one class library. How would you move each class from those libraries which has hundreds of methods when you only need one in each and 70% of the methods are not used in your application ? Classic example of reusable components is arcobjects which is written in c++ and is reused in several programming languages.  They are maintaining  and modifying the legacy code instead of completely migrating it because it is too much of an effort and time.
0 Kudos
AlexanderGray
Honored Contributor
Of course it is all case by case but my point is reuse is just one of the things to think about when programming and it usually shouldn't be the first.  I have worked for people who kept insisting on writing code with reuse in mind.  In my opinion reducing code complexity is a much more important consideration, in most cases.
0 Kudos
RobertPincus
Regular Contributor
I have a form with a button on it. The button's click event activates a tool which in turn gets the a point object. My question is how can the form get the point from the tool so that the x and y values can be used in the form?

Robert
0 Kudos
NeilClemmons
Honored Contributor
I have a form with a button on it. The button's click event activates a tool which in turn gets the a point object. My question is how can the form get the point from the tool so that the x and y values can be used in the form?

Robert


One solution is to write a generic tool that allows the user to click the map (or draw a rectangle, a line, a circle, a polygon or whatever).  The tool would then fire an event and pass in the geometry as one of the arguments.  The code behind your form would include an event handler for this event that does whatever you need to do with that point geometry (for example, select a feature on a certain layer and populate controls with its attributes).  The code behind the button would create a new instance of your tool, subscribe to its event and activate the tool.
0 Kudos
RobertPincus
Regular Contributor
I know how to create a tool that fires an event to open a form. What I want to do is go the other way. Have a form with a button  activate a tool. Have the user click on the map and pass the coordinates back to the form. I tried to follow your narratives on how to do that, but this seems complex. Would you have a simple example that you could share.

Thanks,
Robert
0 Kudos
KenBuja
MVP Esteemed Contributor
This is how I've done it in my VB.Net add-in project. I have a form with several options of different types of features that can be created.

[ATTACH=CONFIG]17601[/ATTACH]

I have a tool called DrawTool that contains the code for the OnMouseDown sub that captures the feature that is drawn.

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

    'Public LineType As String
    Private m_LineFeedback As ESRI.ArcGIS.Display.INewBezierCurveFeedback = Nothing
    Private graphicsContainer As ESRI.ArcGIS.Carto.IGraphicsContainer

    Public Sub New()

    End Sub

    Protected Overrides Sub OnUpdate()

    End Sub

    Protected Overrides Sub OnMouseDown(ByVal arg As ESRI.ArcGIS.Desktop.AddIns.Tool.MouseEventArgs)
        MyBase.OnMouseDown(arg)

'etc


This is the code for the buttons on my form.

   Private Sub Draw_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPoint.Click, btnLocation.Click, btnPolygon.Click, btnFreehand.Click, btnRectangle.Click

        Dim pUID As New ESRI.ArcGIS.esriSystem.UID
        Dim pCommandItem As ESRI.ArcGIS.Framework.ICommandItem


        pUID.Value = My.ThisAddIn.IDs.DrawTool
        pCommandItem = m_application.Document.CommandBars.Find(pUID, False, False)

        Select Case sender.name
                Case "btnPoint"
                    'code to do some things for the Point tool
                Case "btnLocation"
                    'code to do some things for the Location tool
                'etc
        End Select

        m_application.CurrentTool = pCommandItem


0 Kudos