C# OnMouseDown returning an IPoint?

5306
18
03-28-2012 11:11 AM
LucieBoucher1
New Contributor
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
sapnas
by
Occasional Contributor III
If I have understood right you want to store the coordinates every time there is a mouse click event. If so, you can declare a static point variable in your addin tool which gets populated in mouse click event and could be accessed as GetCoord.NewPoint.

 
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
    {
      private static IPoint newpoint = null;
   public static IPoint NewPoint
      {
          get { return newpoint; }
      }
 
 
        public GetCoord()
        {
        }
        protected override void OnUpdate()
        {
        }
        protected override void OnMouseDown(ESRI.ArcGIS.Desktop.AddIns.Tool.MouseEventArgs arg)
        {
            try
            {
               if(newpoint == null)
              {
                   newpoint = new Point();
            
              }              
              newpoint.PutCoords(arg.X,arg.Y);
             //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);
            }
        }
    }
}

0 Kudos
LucieBoucher1
New Contributor
Thanks for your help!

I have tried your solution. 

My GetCoord.cs file now looks like this :
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using ESRI.ArcGIS.Geometry; //For the IPoint

namespace myProject
{
    public class GetCoord : ESRI.ArcGIS.Desktop.AddIns.Tool
    {
        private static IPoint newpoint = null;
        public static IPoint NewPoint
        {
            get { return newpoint; }
        }

        public GetCoord()
        {
        }

        protected override void OnUpdate()
        {
        }

        protected override void OnMouseDown(ESRI.ArcGIS.Desktop.AddIns.Tool.MouseEventArgs arg)
        {
            try
            {
                if (newpoint == null)
                {
                    newpoint = new Point();
                }
                newpoint.PutCoords(arg.X, arg.Y);

            }
            catch (Exception e)
            {
                System.Windows.Forms.MessageBox.Show("Problem to get coordinates : " + e.Message);
            }
        }
    }

}


Then I tried to call the point within another cs file with this code
IPoint newLocation = GetCoord.NewPoint;
System.Windows.Forms.MessageBox.Show("X Coordinate: " + newLocation.X);
System.Windows.Forms.MessageBox.Show("Y Coordinate: " + newLocation.Y);


but I get the following error message :
Non-invocable member myProject.GetCoord.NewPoint cannot be used like a method.

Any clue?
0 Kudos
sapnas
by
Occasional Contributor III
Prior to invoking the point in another cs file did you select the GetCoord tool and clicked the mouse on the map. Do you want to reuse the method or do you want to access the points returned by GetCoord tool?

Can you also post the cs file invoking  GetCoord.NewPoint?
0 Kudos
LucieBoucher1
New Contributor

sshetty said :
Prior to invoking the point in another cs file did you select the GetCoord tool and clicked the mouse on the map.


Indeed, I had not.  When I click on the GetCoord tool, then click on the map, and then on my NewLocation button, I get the apropriate coordinates. 🙂

Now, would it be possible to skip the click on the GetCoord tool?  What I would like is to have the user click on my NewLocation button, then click on the map, and have the process done.  In other words, is it possible to call the GetCoord tool within the NewLocation.OnClick function?  In an ideal world, the GetCoord would not appear on my toolbar, it would only be a tool used within other buttons.

Thanks again for your help!
0 Kudos
sapnas
by
Occasional Contributor III
If you are using Addin button then add below code in onclick method where "ID" is GetCoord id in Config.esriaddinx. Current tool will automatically invoke mouse down event.


ICommandItem cmd = ArcMap.Application.Document.CommandBars.Find("ID", false, false);
              ArcMap.Application.CurrentTool = cmd;
0 Kudos
AlexanderGray
Occasional Contributor III
Your new location tool would have its' own onMouseDown implementation where you would put that same code in it.   The method is designed to be invoked by ArcMap when you mouse down on the map with your tool. You could write a static method that took in the mouseenventargs and the screendisplay as arguments and returns a point, but I don't think it is worth it.  It is only a few lines of code and making a new function for it seems like a hassle.  In my opinion code reuse is rarely worth the trouble and modularity in code is much more handy even if it means writing a few lines of code over and over.  If you really want to, you can make an abstract class that implements mouseenventargs and the tool interface and then inherit the class, but to me that seems like using a cannon to go after flies.
0 Kudos
LucieBoucher1
New Contributor
Your new location tool would have its' own onMouseDown implementation where you would put that same code in it.   The method is designed to be invoked by ArcMap when you mouse down on the map with your tool. You could write a static method that took in the mouseenventargs and the screendisplay as arguments and returns a point, but I don't think it is worth it.  It is only a few lines of code and making a new function for it seems like a hassle.  In my opinion code reuse is rarely worth the trouble and modularity in code is much more handy even if it means writing a few lines of code over and over.  If you really want to, you can make an abstract class that implements mouseenventargs and the tool interface and then inherit the class, but to me that seems like using a cannon to go after flies.


I see.  I therefore understand that I will not create a New Location button, but a New Location tool...  Not that it changes much in the end, but I need to start with the right structure. 


If you are using Addin button then add below code in onclick method where "ID" is GetCoord id in Config.esriaddinx. Current tool will automatically invoke mouse down event.
ICommandItem cmd = ArcMap.Application.Document.CommandBars.Find("ID", false, false);
              ArcMap.Application.CurrentTool = cmd;



I have tried your solution, but my code now crashed ArcGIS.  Thank you very much for your help and for the time you took to answer.  I believe I will go with Alexander's suggestion and save myself trouble by copying the function through all the tools that require it.
0 Kudos
sapnas
by
Occasional Contributor III
It crashes if  you dont add the GetCoord tool on arcmap. Good luck!
0 Kudos
sapnas
by
Occasional Contributor III
BTW you still have to copy  the Mouse down event code in all the tools. The advantage of reusability is less code and errors can be quickly identified and eliminated. Basically fixing  bug in one class versus  fixing the same bug in multiple classes. Ofcourse reusability depends on case by case basis.
0 Kudos