Learn how to retrieve the mouse cursor coordinates not just inside the form, but also when the cursor is located outside of the form, such as on the desktop or when a different application has the focus. We use the GetCursorPos() function from the Windows API.
Form-wide coordinates versus screen coordinates
Using .NET Framework 1.1 or 2.0, retrieving the mouse coordinates is pretty easy, by making use of a couple of properties, as I proven in the tutorial named Mouse Coordinates.
However, .NET Framework doesn’t offer us the possibility to retrieve the mouse coordinates when the mouse leaves the form, and thus the coordinates that are relative to the screen.
There are many cases in which you’ll want them to retrieve the overall cursor coordinates: starting from the upper-left edge of the screen, to the most extreme point, which is the lower-right edge. There is a function in the Windows API which allows us to do just that: GetCursorPos().
Below is a screenshot of the application that I built for this tutorial and which you can download from the link at the top of the project. It’s compiled using .NET 2.0, but you can compile the code with a .NET 1.1 compiler without any changes whatsoever.
Using GetCursorPos() to retrieve the coordinates
To retrieve the global mouse coordinates we need to use unmanaged code, thus add the following using statement:
using System.Runtime.InteropServices; |
GetCursorPost() is located inside user32.dll, so we need to define the attribute:
// We need to use unmanaged code [DllImport(“user32.dll”)] // GetCursorPos() makes everything possible static extern bool GetCursorPos(ref Point lpPoint); |
Add two labels to the form (lblCoordX and lblCoordY), where the X and Y coordinates will be displayed. Also add a timer and set its interval (the Interval property) to 10.
But why do we need a timer anyway?
Well, there doesn’t seem to be a MouseMove event that fires when the cursor is moving, indifferent of the focused application. There is such an event in .NET, but it’s only effective while the mouse hovers the form or some other control in it. So to continously monitor the cursor position we use a timer that gets the mouse cursor coordinates at a short interval (such as 10 milliseconds).
After adding the timer, double click it so that we get to its single event – Tick – and use the following piece of code which calls the Windows API function and updates the two labels:
// New point that will be updated by the function with the current coordinates Point defPnt = new Point(); // Call the function and pass the Point, defPnt GetCursorPos(ref defPnt); // Now after calling the function, defPnt contains the coordinates which we can read lblCoordX.Text = “X = “ + defPnt.X.ToString(); lblCoordY.Text = “Y = “ + defPnt.Y.ToString(); |
Counting traveled pixels
Trying to make this application fun, I decided to calculate the total pixels the mouse travels, more exactly to make a counter.
First declare 5 more variables:
static protected long totalPixels = 0; static protected int currX; static protected int currY; static protected int diffX; static protected int diffY; |
Add one more label to the Form (lblTravel), and a button (btnReset). Now inside the Tick event of the Timer, after the labels showing the X and Y coordinates are updated, use the following code:
// If the cursor has moved at all if (diffX != defPnt.X | diffY != defPnt.Y) { // Calculate the distance of movement (in both vertical and horizontal movement) diffX = (defPnt.X – currX); diffY = (defPnt.Y – currY); // The difference will be negative if the cursor was moved left or up // and if it is so, make the number positive if (diffX < 0) { diffX *= -1; } if (diffY < 0) { diffY *= -1; } // Add to the “pixels traveled” counter totalPixels += diffX + diffY; // And display inside a label lblTravel.Text = “You have traveled “ + totalPixels + ” pixels”; } // We need this to see the difference of pixels between two mouse movements currX = defPnt.X; currY = defPnt.Y; |
Now to complete the application, double click the btnReset button to get to the Click event , and use the following line to reset the counter variable:
totalPixels = 0; |