Introduction

Did you ever need a button that mimics the auto-repeat behavior of the keyboard? Button, that when clicked and held, emits a sequence of MouseDown events as long as the button is pressed.

I needed such a button in one of my programa. I quickly realized that it could be done very easily.


Background


The basic idea is the following: timer control periodically executes code that simulates multiple MouseDown events as long as the button is pressed down.


The Code


Since I promised that it is simple and quick to implement, let's start.

First, I created the RepeatButton user control inherited from the Button.

public class RepeatButton : Button  

Second, I added a Timer control and renamed it to timerRepeater. For a start, I added an empty tick event handler:

private void timerRepeater_Tick(object sender, EventArgs e)
{
 //Will be coded later
}

Third, I defined two new properties to control repeat timing:

[DefaultValue(400)]
public int InitialDelay { set; get; }

[DefaultValue(62)]
public int RepeatInterval { set; get; } 

I've made sure that properties are properly initialized in the constructor:

public RepeatButton():base()
{
    InitializeComponent();
    InitialDelay = 400;
    RepeatInterval = 62;
}

Next, I overrode the OnMouseDown event handler. The new code does three things:

MouseEventArgs MouseDownArgs = null;
protected override void OnMouseDown(MouseEventArgs mevent)
{
    MouseDownArgs = mevent;
    timerRepeater.Enabled = false;
    timerRepeater_Tick(null, EventArgs.Empty);
}

And finally the key element of code where repeat loop is happening. Time to fill timerRepeater_Tick with usable code.

This handler is called explicitly from OnMouseDown when the user presses button down. The first line contains a call to base.OnMouseDown. This is where the actual MouseDown event is handled and where the code that hosts the control gets notified that the mouse was pressed down.

Next

If timerRepeater is not enabled (when timerRepeater_Tick is called from OnMouseDown, it is never enabled), it means that this code is called for the first time after the mouse was pressed down. In such a case, timerRepeater.Interval is set to InitialDelay, otherwise it is set to RepeatInterval.

And finally in the last line of code, the timerRepeater.Enabled property is set to true. This will cause timerRepeater_Tick to be continuously called at intervals of time set in the Interval property.

private void timerRepeater_Tick(object sender, EventArgs e)
{
    base.OnMouseDown(MouseDownArgs);
    if (timerRepeater.Enabled)
        timerRepeater.Interval = RepeatInterval;
    else
        timerRepeater.Interval = InitialDelay;
 
     timerRepeater.Enabled = true;
}

The above piece of code will be called forever after the mouse is initially pressed down. We need to stop this behavior as soon as the mouse is up again. Nothing simpler. One extra line in OnMouseUp is needed that sets the timerRepeater.Enabled property to false. This will stop the timerRepeater_Tick loop instantly.

protected override void OnMouseUp(MouseEventArgs mevent)
{
    base.OnMouseUp(mevent);
    timerRepeater.Enabled = false;
}

And that's all, fully functional RepeatButton in probably even less than 10 minutes.

The entire code for RepeatButton is presented below, so you can copy it and paste to your solution:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
using System.Windows.Forms;
using System.ComponentModel;
 
namespace RepeatButtonControl
{
    public class RepeatButton : Button
    {
        private Timer timerRepeater;
        private IContainer components;
    
        public RepeatButton():base()
        {
            InitializeComponent();
 
            InitialDelay = 400;
            RepeatInterval = 62;
        }
 
        [DefaultValue(400)]
        public int InitialDelay { set; get; }
 
        [DefaultValue(62)]
        public int RepeatInterval { set; get; }
 
        private void InitializeComponent()
        {
            this.components = new System.ComponentModel.Container();
            this.timerRepeater = new System.Windows.Forms.Timer(this.components);
            this.SuspendLayout();
            this.timerRepeater.Tick += new System.EventHandler(this.timerRepeater_Tick);
            this.ResumeLayout(false);
         }
        
        MouseEventArgs MouseDownArgs = null;
        protected override void OnMouseDown(MouseEventArgs mevent)
        {
            //Save arguments
            MouseDownArgs = mevent;
            timerRepeater.Enabled = false;
            timerRepeater_Tick(null, EventArgs.Empty);
        }
 
        private void timerRepeater_Tick(object sender, EventArgs e)
        {
 
            base.OnMouseDown(MouseDownArgs);
            if (timerRepeater.Enabled)
                timerRepeater.Interval = RepeatInterval;
            else
                timerRepeater.Interval = InitialDelay;
 
            timerRepeater.Enabled = true;
        }
 
        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            base.OnMouseUp(mevent);
            timerRepeater.Enabled = false;
        }
    }
} 

Using the Code

You can code along repeating all steps described in the article and develop a repeat button from scratch, it's easy and fun.

If you want to save time, you can also download the attached source code. It contains the RepeatButton source code and demo application illustrating the behavior of the repeat button. Not much explanation needed.

You press the repeatButton on the demo main screen, hold it, and watch how events are generated as in the screenshot shown below:

 

Downloadable zip file contains also help file (chm). Please note, that since you are downloading this file from the Internet, in order to use it you have to unblock it first. You can do it from Windows explorer: right_click on the help file, select 'Properties', click 'Unblock' button.  


Home  bullet Products  bullet Downloads  bullet About Us  bullet Contact Us

Credit Card Logo