Introduction
This article shows how to snap the mouse cursor to the center of a control on MouseEnter
and hold it for a short time. After the allotted time (the default is 1/4 second), the control releases its grip on the cursor. This method will work for any control - the example below has both a Button
and a PictureBox
:
Background
I created a utility whose window could be resized to a very small interface to stay out of the way (like WinAmp - a small bar with no caption). The buttons, when at their smallest size, were difficult to press. I needed a way to guide the user to the center of a button so they did not accidentally hit the adjoining button.
When this: scales to this: , it is difficult to get the mouse over a button.
By implementing these events, the user can easily position the mouse over a control, even if it is too small to accurately click. The sticky hold on the button also ends quickly so it does not become an annoyance to the user.
Using the code
To make a control sticky, you need to set its mouse events MouseEnter
and MouseMove
to the StartSnap
and CheckSnap
event handlers.
C#
public partial class Form1 : Form
{
private DateTime dtSnapEnd;
private double dReleaseTime = 250;
private void SnapToCenter(Control control)
{
Point pCenter = control.PointToScreen(new Point(0, 0));
pCenter.X += control.Width / 2;
pCenter.Y += control.Height / 2;
Cursor.Position = pCenter;
}
private void StartSnap(object sender, EventArgs e)
{
SnapToCenter((Control)sender);
dtSnapEnd = DateTime.Now.AddMilliseconds(dReleaseTime);
}
private void CheckSnap(object sender, MouseEventArgs e)
{
if (DateTime.Now < dtSnapEnd)
{
SnapToCenter((Control)sender);
}
}
}
In Design View:
- Add a control to your form.
- On the control properties, switch to Events and set the
MouseEnter
event to StartSnap
. - Set the
MouseMove
event to CheckSnap
.
VB.NET
We need to handle events a little differently in Visual Basic, because VB.NET does not use generic event handlers (at least from the design interface):
- Create your form and add controls to it.
- In the form's
Form_Load
event, add the following for each control:
AddHandler Button1.MouseEnter, AddressOf StartSnap
AddHandler Button1.MouseMove, AddressOf CheckSnap
AddHandler YourControlHere.MouseEnter, AddressOf StartSnap
AddHandler YourControlHere.MouseMove, AddressOf CheckSnap
Here is the full VB code to handle the events:
Public Class Form1
Private dSnapEnd As Date
Private dReleaseTime As Double = 250
Private Sub SnapToCenter(ByVal control As Control)
Dim pCenter As Point
pCenter.X = control.Width / 2
pCenter.Y = control.Height / 2
Cursor.Position = control.PointToScreen(pCenter)
End Sub
Private Sub StartSnap(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
SnapToCenter(CType(sender, Control))
dSnapEnd = dSnapStart.AddMilliseconds(dReleaseTime)
End Sub
Private Sub CheckSnap(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.MouseEventArgs)
If Date.Now < dSnapEnd Then
SnapToCenter(CType(sender, Control))
End If
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
AddHandler Button1.MouseEnter, AddressOf StartSnap
AddHandler Button1.MouseMove, AddressOf CheckSnap
AddHandler YourControlHere.MouseEnter, AddressOf StartSnap
AddHandler YourControlHere.MouseMove, AddressOf CheckSnap
End Sub
End Class
Acknowledgements
Thanks to Karl Moore for the code on centering the cursor on the control.
History
- 2008.09.17 - Initial article with sample applications.