Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

.NET port of Joe's AutoRepeat Button class

0.00/5 (No votes)
16 Apr 2002 1  
This ports Joe Newcomer's AutoRepeat Button class to a .NET control

Introduction

This is my attempt at porting Joseph M Newcomer's AutoRepeat Button Class to .NET. I was quite enthusiastic about doing this specially since I am a big fan of Joe and also because I had never created a .NET control of my own. This is actually my first crack at doing this.

The Control

Well a repeat button is a button on which you can click and then when you keep it clicked something happens. For instance,  if you have a button that you click to increase some value by 1. Then if you keep the button clicked, the value keeps changing. As if you had clicked on the button multiple times.

Just as in Joe's button auto-repeat class, my control also only handles the mouse. If you use the keyboard to click on a button (by using the ENTER key), then the repeat rate will be that of your keyboard. This has been left out in this version and might be a feature for later. Maybe when Joe updates his class, I'll update mine as well.

The control was derived from the System.Windows.Forms.Button class and thus acts as a button in every other way. It has two new properties though. InitialDelay and RepeatDelay which are used to set the initial delay before the button starts auto-repeating and the repeat delay between each repeat.

Using the control

Well, if you compile it as a DLL like I did, then you can add it as a .NET control. Which means you'll have it on your toolbox and you can add it just as you'd add any other control. You can take the button's properties and set the InitialDelay and RepeatDelay property. You cannot set it to less than 100. All units are in milliseconds. If you want to add it via code then you can add it just as you would add a normal Button control.

Tech Details

Just as Joe did in his class, I use a timer. I have a private Timer variable called m_timer. I have two bool variables called down and once. Then I also have two private variables for the initial delay and repeat delay properties. In the constructor I add handlers for the MouseUp and MouseDown events. I also associate a function with my timer. By default the timer is disabled.

Now in my MouseDown handler I do three  things. I set the down boolean variable to true. I set the timer interval to the InitialDelay property and then I enable the timer. In my MouseUp handler I simply disable the timer and also make down false. Initially I thought I'd have to capture the mouse too. Because the user might click on a button and then drag the mouse out of the button and release it. In normal win32 programming you won't get the mouse up messages if this happens. But to my surprise [James Johnson has confirmed this. I woke him up in the middle of the night to get this confirmed. Poor James!] I found that even if the mouse is released after being dragged out, we still get the MouseUp event handler called. I guess the framework internally does all the capturing stuff for us.

In my timer function, I first change the timer interval to the RepeatDelay property. Now I check if the down variable is true which means that the mouse button is currently down. And if it is down, I use the PerformClick() function to simulate a mouse click. I also set the once boolean variable to true just as Joe does in his class, though instead of a boolean variable, Joe actually maintains a count of the number of repeats completed. I also override the OnClick function. I call the base class if either down is true or if the once variable is false, because that indicates that the repeats were not performed as could happen with a quick mouse click. If I didn't do this once check, we'd always end up with one extra repeat which is to be avoided.

Complete source listing

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Windows.Forms;

namespace RepeatButton
{    
    public class RepeatButton : System.Windows.Forms.Button
    {
        private Timer m_timer;
        private bool down=false;
        private bool once=false;
        private int m_initdelay=1000;
        private int m_repdelay=400;

        public RepeatButton()
        {
            this.MouseUp += 
                new MouseEventHandler(RepeatButton_MouseUp);
            this.MouseDown += 
                new MouseEventHandler(RepeatButton_MouseDown);

            m_timer = new Timer();            
            m_timer.Tick += new EventHandler(timerproc);
            m_timer.Enabled=false;
        }

        private void timerproc(object o1, EventArgs e1)
        {                
            m_timer.Interval = m_repdelay;
            if(down)
            {
                once=true;
                this.PerformClick();
            }
                
        }

        protected override void OnClick(EventArgs e)
        {
            if(!once || down)
                base.OnClick(e);
        }

        

        private void RepeatButton_MouseDown(object sender, 
            System.Windows.Forms.MouseEventArgs e)
        {
            m_timer.Interval=m_initdelay;
            m_timer.Enabled=true;
            down=true;
        }

        private void RepeatButton_MouseUp(object sender, 
            System.Windows.Forms.MouseEventArgs e)
        {
            m_timer.Enabled=false;
            down=false;
        }

        public int InitialDelay
        {
            get
            {
                return m_initdelay;
            }
            set
            {
                m_initdelay = value;
                if(m_initdelay<100)
                    m_initdelay=100;
            }
        }

        public int RepeatDelay
        {
            get
            {
                return m_repdelay;
            }
            set
            {                
                m_repdelay = value; 
                if(m_repdelay<100)
                    m_repdelay=100;
            }
        }    

    }
}

Conclusion

You may build this control as a class library which makes it easier to use it, because you can simply drag/drop it into a form using the form designer and you can also set properties using VS.NET properties window. But if you don't want to do that, you may also include this class in your project and manually add the control to your form.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here