Link to home
Create AccountLog in
Avatar of NackJich
NackJich

asked on

Using C# How can I sample the current mouse position in a window

The title is a bit of an over-simplification! What i would like to do is to create a full screen window and manually move my mouse around this window. I would like to have my program sample the mouse coordinates relative to the screen at short intervals to enable me to record a series of points which describe the object I have just drawn. I'm new to c# and to programming so you may need to be gentle!! Thanks. Ian
Avatar of Kyle Abrahams, PMP
Kyle Abrahams, PMP
Flag of United States of America image

Essentially you would use the mouse_move event.

The code below is a little more complex, but I found it elegant as it was global to the application rather then a form.

Let know if you have questions:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace GlobalMouseEvents
{
   public partial class Form1 : Form
   {
     //normal form init.
      public Form1()
      {
          //create a new global mouse handler
         GlobalMouseHandler gmh = new GlobalMouseHandler();
   
         //subscribe TheMouseMoved, handler is gmh_TheMouseMoved
         gmh.TheMouseMoved += new MouseMovedEvent(gmh_TheMouseMoved);
         
        //add the filter for housekeeping / windows processing.
         Application.AddMessageFilter(gmh);

         InitializeComponent();
      }
        
     // when the mouse is moved, this event will fire.
      void gmh_TheMouseMoved()
      {
         Point cur_pos = System.Windows.Forms.Cursor.Position;
         System.Console.WriteLine(cur_pos);
      }
   }

//here's how the capture is actually done:
   public delegate void MouseMovedEvent();

   public class GlobalMouseHandler : IMessageFilter
   {
       //windows defined.
      private const int WM_MOUSEMOVE = 0x0200;

      // this is a custom event that will be raised by the class.
      public event MouseMovedEvent TheMouseMoved;

      #region IMessageFilter Members

     // overriding IMessageFilter
      public bool PreFilterMessage(ref Message m)
      {
         if (m.Msg == WM_MOUSEMOVE)
         {
             // if I'm subscribed to something
            if (TheMouseMoved != null)
            {
               // fire that event.
               TheMouseMoved();
            }
         }
         // Always allow message to continue to the next filter control
         return false;
      }

      #endregion
   }
}

Open in new window

Use the MouseMove() event as suggested and store the points in a List<>.  Then add those points to a GraphicsPath() using AddLines().
Avatar of NackJich
NackJich

ASKER

Hi Thanks for your comments. Kyle I'm using Visual Studio 2015 Enterprise. I created a new project: a Windows Forms Application. There were two errors: The name "InitializeComponent" does not exist in the current context, which i think I fixed - see code below, and Program does not contain a static 'Main' method suitable for an entry point. (Not sure what to do here). Thanks!

      using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace GlobalMouseEvents
{
    public partial class Form1 : Form
    {
        //normal form init.
        public Form1()
        {
            //create a new global mouse handler
            GlobalMouseHandler gmh = new GlobalMouseHandler();

            //subscribe TheMouseMoved, handler is gmh_TheMouseMoved
            gmh.TheMouseMoved += new MouseMovedEvent(gmh_TheMouseMoved);

            //add the filter for housekeeping / windows processing.
            Application.AddMessageFilter(gmh);

            InitializeComponent();
        }

        private void InitializeComponent()
        {
            throw new NotImplementedException();
        }

        // when the mouse is moved, this event will fire.
        void gmh_TheMouseMoved()
        {
            Point cur_pos = System.Windows.Forms.Cursor.Position;
            System.Console.WriteLine(cur_pos);
        }
    }

    //here's how the capture is actually done:
    public delegate void MouseMovedEvent();

    public class GlobalMouseHandler : IMessageFilter
    {
        //windows defined.
        private const int WM_MOUSEMOVE = 0x0200;

        // this is a custom event that will be raised by the class.
        public event MouseMovedEvent TheMouseMoved;

        #region IMessageFilter Members

        // overriding IMessageFilter
        public bool PreFilterMessage(ref Message m)
        {
            if (m.Msg == WM_MOUSEMOVE)
            {
                // if I'm subscribed to something
                if (TheMouseMoved != null)
                {
                    // fire that event.
                    TheMouseMoved();
                }
            }
            // Always allow message to continue to the next filter control
            return false;
        }

        #endregion
    }
There should be a program.CS which has the Main function in it.  (Be sure you're viewing all files).

The initialize component is usually part of the Form Constructor.
Hello again.
I'm still trying to understand the basics of c#.
However I'm one error away from testing your script!
Line 31:  Point cur_pos = System.Windows.Forms.Cursor.Position;
This was simplified to: Point cur_pos = Cursor.Position;  
For this line there is an error:
Severity      Code      Description      Project      File      Line      Suppression State
Error      CS0029      Cannot implicitly convert type 'System.Drawing.Point' to 'GlobalMouseEvents.Form1.Point'      Experts Mouse Move      C:\Users\User\Documents\Visual Studio 2015\Projects\Experts Mouse Move\Experts Mouse Move\Program.cs      44      Active
What can I do to solve this? Thank you..
try:

System.Drawing.Point cur_pos = Cursor.Position;

Open in new window

Hello again!
This code works and compiles etc, but when I run the executable all I see is a brief flash of a window? Do I need a delay or a pause?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace GlobalMouseEvents
{
    public partial class Form1 : Form
    {
        //normal form init.
       
        static void Main(string[] args)
        { }
        public Form1()

        {
            InitializeComponent();
            {
               
            }
            //create a new global mouse handler
            GlobalMouseHandler gmh = new GlobalMouseHandler();

            //subscribe TheMouseMoved, handler is gmh_TheMouseMoved
            gmh.TheMouseMoved += new MouseMovedEvent(gmh_TheMouseMoved);

            //add the filter for housekeeping / windows processing.
            Application.AddMessageFilter(gmh);

           
        }

        private void InitializeComponent()
        {
            this.SuspendLayout();
            //
            // Form1
            //
            this.ClientSize = new System.Drawing.Size(932, 465);
            this.Name = "Form1";
            this.ResumeLayout(false);

        }

        // when the mouse is moved, this event will fire.
        void gmh_TheMouseMoved()
        {
            System.Drawing.Point cur_pos = Cursor.Position;
            System.Console.WriteLine(cur_pos);
        }

        private class Point
        {
        }
    }

    //here's how the capture is actually done:
    public delegate void MouseMovedEvent();

    public class GlobalMouseHandler : IMessageFilter
    {
        //windows defined.
        private const int WM_MOUSEMOVE = 0x0200;

        // this is a custom event that will be raised by the class.
        public event MouseMovedEvent TheMouseMoved;

        #region IMessageFilter Members

        // overriding IMessageFilter
        public bool PreFilterMessage(ref Message m)
        {
            if (m.Msg == WM_MOUSEMOVE)
            {
                // if I'm subscribed to something
                if (TheMouseMoved != null)
                {
                    // fire that event.
                    TheMouseMoved();
                }
            }
            // Always allow message to continue to the next filter control
            return false;
        }
   

        #endregion
    }
}
It should display a blank form, and you should be able to see the output  in the console in visual studio.

Note that you can also use Debug.WriteLine and that will show up in the debug window's output.  (Note you'll have to build it in debug instead of release for that to appear).

I believe you're getting a brief flash because the main is blank.


This is just a windows Form Application correct?  Your main should be in a program.CS file with something like:

    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
Hi Kyle
I have my window being displayed successfully now, but mouse move events do not result in any changes?
MouseMove-Windows-Forms-App.sln
You only sent the solution file.  You need to zip up the whole folder.
If I zip the entire folder ExpertsExchange prompts that exe files are not on the list of allowed extensions. Do I simply exclude all the exes?
you can exclude the exes.
This just popped up for auto close.  I haven't had a chance to review and will be away until Tuesday.  Will take a look at it when I get back.
ASKER CERTIFIED SOLUTION
Avatar of Kyle Abrahams, PMP
Kyle Abrahams, PMP
Flag of United States of America image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
Thanks Kyle. Kudos you took the time to do this..