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

Auto-repeat Button in 10 Minutes

4.68/5 (26 votes)
31 Oct 2018CPOL4 min read 57.7K   1.2K  
Simple WinForms auto-repeat button in a few lines

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 my program. As usual, I started my search with CodeProject, and found an interesting article .NET port of Joe's AutoRepeat Button class by Nish Sivakumar. The presented code did its job and I was about to copy and paste it to my project when I realized that I can implement the desired functionality using simpler logic and with fewer lines of code.

Background

The basic idea is the same as in the original article: 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.

C#
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:

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

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

C#
[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:

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

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

  • It saves the event argument to an external variable. This is needed because the event actually will be handled by the timerRepeat_Tick event handler that needs this information.
  • It makes sure that timerRepeater is disabled. This line of code is not really needed since timerRepeater is always disabled when OnMouseDown is executed. I added it here for clarity of code.
  • It calls timerRepeater_Tick that will immediately handle the initial click and all repetitions as long as the mouse is kept down.
C#
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.

C#
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.

C#
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:

C#
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:

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

History

  • August 1, 2013 - Initial release
  • September 17, 2013 - Updated source code: improved style, added comments, added the Dispose method, added help file for control (chm)
  • December 13, 2013 - Minor article text improvements 

License

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