Add Image next to Mouse Cursor with ArcMap Add-in Button

250
0
11-09-2023 06:20 AM
Labels (1)
LaurenPeckman
New Contributor III

I am working on an add-in program for ArcMap 10.5. 

When the user clicks the add-in button, an image displays in the winform picture box. (For this example, that image comes from solution's Resource folder, but that does not matter for now). 

When the user clicks "Run" on the winform, the program is meant to grab the image from the picture box, make it the same size as the mouse cursor, and then add that image NEXT TO the mouse cursor (preferably to the right of the existing mouse cursor). 

The image floats along next to the mouse cursor, until the user clicks the "Close" button. 

Right now, I cannot get this image addition to display next to my mouse cursor. 

Here is my code thus far: 


 

 

 

using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Framework;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.Geometry;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.ComponentModel;
using System.Data;
using System.Text;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using LineByCursor.Properties;


namespace LineByCursor
{

    // get X,Y from mouse event 
    // community.esri.com/t5/arcobjects-sdk-questions/add-in-button-mouse-down-capture/td-p/542368

    public partial class Form1 : Form
    {
        private IGraphicTracker m_tracker;
        // allows one to loop through the generated ids
        private List<int> m_ids;

        // private string m_xmlPath;

        private MouseHook m_mh;
        private IPoint m_lastLoc;
        private int m_moveCount = 0;
        private Image resourceImage = Resources.simpleDiagonalLine;

        public Form1()
        {
            InitializeComponent();
            pictureBox1.Image = resourceImage;
            pictureBox1.Visible = true;

            m_tracker = new GraphicTrackerClass();
            //allows one to loop through the generated ids
            m_ids = new List<int>();                     
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            m_mh = new MouseHook();
            m_mh.SetHook();
            m_mh.MouseMoveEvent += mh_MouseMoveEvent;

            this.Location = Settings.Default.MyLoc;

            Rectangle rect = Screen.GetWorkingArea(this);

            if (this.Size.Width + this.Location.X > rect.Right)
            {
                this.Location = new System.Drawing.Point(rect.Right - Size.Width, this.Location.Y);
            }
            if (this.Size.Height + this.Location.Y > rect.Bottom)
            {
                this.Location = new System.Drawing.Point(this.Location.X, rect.Bottom - Size.Height);
            }
            if (this.Location.Y < rect.Top)
            {
                this.Location = new System.Drawing.Point(this.Location.X, rect.Top);
            }
            if (this.Location.X < rect.Left)
            {
                this.Location = new System.Drawing.Point(rect.Left, this.Location.Y);
            }
        }

        private void buttonRun_Click(object sender, EventArgs e)
        {
            try
            {
                IMouseCursor appCursor = new MouseCursorClass();
                appCursor.SetCursor(2);

                m_tracker.RemoveAll();
                // from Distance Halo - needed? 
                m_ids.Clear();


                // Load the image from your resources (assuming it's a PNG file?)
                Image image = pictureBox1.Image;

                int cursorSize = SystemInformation.CursorSize.Width; // Assuming the cursor size is a square

                // Create a new Bitmap with the desired size
                Bitmap resizedImageBMP = new Bitmap(cursorSize, cursorSize);

                using (Graphics g = Graphics.FromImage(resizedImageBMP))
                {
                    // Draw the original image onto the new Bitmap
                    g.DrawImage(image, new Rectangle(0, 0, cursorSize, cursorSize));
                }

                // Now, the "resizedImage" Bitmap will have the same size as the cursor

                IPictureMarkerSymbol picMarkSymbol = new PictureMarkerSymbolClass();
                picMarkSymbol.Picture = (stdole.IPictureDisp)ESRI.ArcGIS.ADF.COMSupport.OLE.GetIPictureDispFromBitmap(resizedImageBMP);

                ISymbol symbol = (ISymbol)picMarkSymbol;

                double radius = 10; // just off-setting from cursor, so not on top of it ... I think? 
                string units = string.Empty;
                IGeometry geometry = BufferGeometry(radius, units);

                m_tracker.Initialize(ArcMap.Document.FocusMap);

                IGraphicTrackerSymbol trackerSymbol = m_tracker.CreateSymbol(symbol, null);
                int id = m_tracker.Add(geometry, trackerSymbol);
                m_ids.Add(id);
                m_tracker.SetScaleMode(id, esriGTScale.esriGTScaleAuto);

                m_tracker.SetVisible(id, false); // also try true?
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error - btnDraw_Click");
            }
        }

        private IGeometry BufferGeometry(double radius, string units)
        {
            var map = ArcMap.Document.FocusMap;
            var point = ArcMap.Document.CurrentLocation;
            var projected = map.SpatialReference as IProjectedCoordinateSystem;
            // double newRadius = 0.0;

            var topoOperator = (ITopologicalOperator)point;
            var polygon = topoOperator.Buffer(radius);

            return polygon;
        }

        private void pictureBox1_Click(object sender, EventArgs e)
        {

        }

        private void mh_MouseMoveEvent(object sender, MouseEventArgs e)
        {
            IPoint currentLoc = ArcMap.Document.CurrentLocation;
            if (m_lastLoc != null && m_tracker.Count > 0)
            {
                if (currentLoc.X != m_lastLoc.X || currentLoc.Y != m_lastLoc.Y)
                {
                    foreach (int id in m_ids)
                    {
                        m_tracker.SetVisible(id, true);
                        m_tracker.MoveTo(id, currentLoc.X, currentLoc.Y, currentLoc.Z);
                        m_moveCount = 0;
                    }
                }
                else
                {
                    m_moveCount++;
                    if (m_moveCount >= 10)
                    {
                        foreach (int id in m_ids)
                        {
                            m_tracker.SetVisible(id, false);
                            m_moveCount = 0;
                        }
                    }
                }
            }
            m_lastLoc = new PointClass();
            m_lastLoc.X = currentLoc.X;
            m_lastLoc.Y = currentLoc.Y;
        }



        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            m_mh.UnHook();

            m_tracker.RemoveAll();
            m_ids.Clear();

            if (this.WindowState == FormWindowState.Normal)
            {
                Settings.Default.MyLoc = this.Location;
            }
            else
            {
                Settings.Default.MyLoc = this.RestoreBounds.Location;
            }
            Settings.Default.Save();
        }

        private void buttonClose_Click(object sender, EventArgs e)
        {
            //this.Close();
            // this.Close();   
            Close();
        }
    }

    public class Win32Api
    {
        [StructLayout(LayoutKind.Sequential)]
        public class POINT
        {
            public int x;
            public int y;
        }
        [StructLayout(LayoutKind.Sequential)]
        public class MouseHookStruct
        {
            public POINT pt;
            public int hwnd;
            public int wHitTestCode;
            public int dwExtraInfo;
        }
        public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern bool UnhookWindowsHookEx(int idHook);
        [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
        public static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);
    }

    public class MouseHook
    {
        private System.Drawing.Point point;
        private System.Drawing.Point Point
        {
            get { return point; }
            set
            {
                if (point != value)
                {
                    point = value;
                    if (MouseMoveEvent != null)
                    {
                        var e = new MouseEventArgs(MouseButtons.None, 0, point.X, point.Y, 0);
                        MouseMoveEvent(this, e);
                    }
                }
            }
        }
        private int hHook;
        private const int WM_MOUSEMOVE = 0x200;
        public const int WH_MOUSE_LL = 14;

        public Win32Api.HookProc hProc;

        public MouseHook()
        {
            this.Point = new System.Drawing.Point();
        }

        public int SetHook()
        {
            hProc = new Win32Api.HookProc(MouseHookProc);
            hHook = Win32Api.SetWindowsHookEx(WH_MOUSE_LL, hProc, IntPtr.Zero, 0);
            return hHook;
        }

        public void UnHook()
        {
            Win32Api.UnhookWindowsHookEx(hHook);
        }

        private int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            Win32Api.MouseHookStruct MyMouseHookStruct = (Win32Api.MouseHookStruct)Marshal.PtrToStructure(lParam, typeof(Win32Api.MouseHookStruct));
            if (nCode < 0)
            {
                return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
            }
            else
            {
                this.Point = new System.Drawing.Point(MyMouseHookStruct.pt.x, MyMouseHookStruct.pt.y);
                return Win32Api.CallNextHookEx(hHook, nCode, wParam, lParam);
            }
        }

        public delegate void MouseMoveHandler(object sender, MouseEventArgs e);
        public event MouseMoveHandler MouseMoveEvent;
    }
}

 

 

 

 

0 Kudos
0 Replies