Sticky Snap-to-Center Controls






4.76/5 (18 votes)
Make your controls snap the cursor to their center and hold it for a short time.
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
{
// When the Snap Hold should break
private DateTime dtSnapEnd;
// Duration of the Snap Hold - set this value to
// determine how long we hold the cursor
private double dReleaseTime = 250;
private void SnapToCenter(Control control)
{
Point pCenter = control.PointToScreen(new Point(0, 0));
// get the center of the control
pCenter.X += control.Width / 2;
pCenter.Y += control.Height / 2;
// set the cursor position to the center
Cursor.Position = pCenter;
}
// Event to handle MouseEnter events
private void StartSnap(object sender, EventArgs e)
{
// start by centering the mouse
SnapToCenter((Control)sender);
// set the time when the snap should break
dtSnapEnd = DateTime.Now.AddMilliseconds(dReleaseTime);
}
// Event to handle MouseMove events
private void CheckSnap(object sender, MouseEventArgs e)
{
// if we have not passed the Snap End time,
// then center the mouse
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 toStartSnap
. - Set the
MouseMove
event toCheckSnap
.
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
' When the Snap Hold should break
Private dSnapEnd As Date
' Duration of the Snap Hold - set this value to
' determine how long we hold the cursor
Private dReleaseTime As Double = 250
Private Sub SnapToCenter(ByVal control As Control)
Dim pCenter As Point
' get the center of the control
pCenter.X = control.Width / 2
pCenter.Y = control.Height / 2
' Set the cursor to the center
Cursor.Position = control.PointToScreen(pCenter)
End Sub
' Event to handle MouseEnter events
Private Sub StartSnap(ByVal sender As System.Object, _
ByVal e As System.EventArgs)
' Start by snapping the cursor to the center
SnapToCenter(CType(sender, Control))
' Set the starting and ending snap times
dSnapEnd = dSnapStart.AddMilliseconds(dReleaseTime)
End Sub
' Event to handle MouseMove events
Private Sub CheckSnap(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.MouseEventArgs)
' If we've not reached the SnapEnd time, center the mouse
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
' Add the event handlers for each control.
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.