Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

Sticky Snap-to-Center Controls

4.76/5 (20 votes)
17 Sep 2008CPOL2 min read 1   1.1K  
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:

StickySnaptoCenter.png

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: large.png scales to this: small.PNG, 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#

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:

  1. Add a control to your form.
  2. On the control properties, switch to Events and set the MouseEnter event to StartSnap.
  3. 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:
VB
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:

VB
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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)