We all pretty much take cursors for granted, don’t we? You wave your mouse about and the cursor obligingly follows. Easy. But what happens if you want to take control of the cursor? Sometimes it’s not quite so easy. Based on problems I’ve seen raised in the past few years, here are a few techniques you might find useful when it comes to dealing with the cursor.
Cursor on a Windows Form
This is fairly straightforward. Let’s start with the case where you want to know the position of the cursor when the user clicks on the form.
The Cursor – or Windows.Forms.Cursor to give it its proper name – has a useful property named Position. This returns a System.Drawing.Point. And that point has two values – x and y.
The x value represents the number of pixels from the left edge of the form, and the y value represents the number of pixels down from the top.
So to get the value of that mouse click, you can use code like the following:
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
Handles Me.MouseDown
Dim pt As Point = Cursor.Position
Console.WriteLine(pt.ToString)
End Sub
This will return the two locations of the point, i.e. the x and y:
{X=661,Y=281}
Most often you’ll want the x and y values separately, so a better call would be:
Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
Handles Me.MouseDown
Console.WriteLine("Mouse clicked on Form at position {0} / {1}", Cursor.Position.X, Cursor.Position.Y)
End Sub
where you’ll get two separate values:
Mouse clicked on Form at position 721 / 480
Moving cursor to a new location on the screen
Try this code in a button click to move the cursor to a pre-selected position:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Cursor.Position = New Point(25, 25)
End Sub
When you run it, the cursor will move to point 25,25 on the screen. There’s the key phrase, though – on the screen. Even though you think you’re working with the Windows.Forms.Cursor, the mouse cursor looks at the system wide situation and it will place the cursor up at the top left of the screen. Now of course if you’re in full screen mode or you’ve specifically placed the form with its top left corner at 0,0 then this will work fine. But if this isn’t the situation, then you need a rethink.
Moving cursor to a new location on the Form
What you have to do is restrict the cursor to work within the bounds of the form, not the screen. And once again there’s a handy little property that you probably wouldn’t have thought of right away (well, at least I didn’t!), and that’s the Clip property. What this does is that defines a rectangle beyond which the cursor mustn’t look. So if you set this bounding rectangle to the area of the form, then of course the point will be restricted to the form area.
Here’s the code that’ll do the trick:
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Me.Cursor = New Cursor(Cursor.Current.Handle)
Cursor.Position = New Point(Cursor.Position.X + 30, 490)
Cursor.Clip = New Rectangle(Me.Location, Me.Size)
End Sub
As you can see, first it grabs the handle of the current cursor, and then it sets the new position. Finally, it clips the area within which the cursor can operate. This is definitely one of those “easy when you know it” techniques, that’s really frustrating if you don’t!
If you need simply to move the cursor to a new location on the form relative to its current location, then the code’s much easier. You only need to add (or subtract) the number of pixels you want to move horizontally and vertically:
Cursor.Position = New Point(Cursor.Position.X + 30, Cursor.Position.Y + 30)
Identifying the cursor location in a control
The last scenario I want to cover is where the user clicks on a control, such as a PictureBox, and you want to know the x and y values within the PictureBox, not the form. The way to work this one is to use the PointToClient method of the PictureBox (or other control, if necessary). This method will take any specified location on the screen and set this in context of the control that lies at that point. So, when you click on the PictureBox, PointToClient takes the screen locations, and works out where the Windows Form sits within the screen and where the PictureBox sits within the form. It then does a quick bit of math and returns a value that represents the number of pixels from the left and top of the control to the cursor’s current location. (This usually being a point where you’ve clicked in the control, although it doesn’t have to be. If the cursor is static and you have some way of firing the event without moving the cursor, you’ll still get those values back.
Here’s the code:
Private Sub PictureBox1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Handles PictureBox1.Click
PicBoxCursorPosition = Me.PictureBox1.PointToClient(Cursor.Position)
Console.WriteLine("Mouse clicked on Picture Box at position {0} / {1}",
PicBoxCursorPosition.X, PicBoxCursorPosition.Y)
End Sub
So there you are, a few quick fixes for frustration free cursor control.