Click here to Skip to main content
11,632,104 members (75,221 online)
Click here to Skip to main content

.NET port of Joe's AutoRepeat Button class

, 16 Apr 2002 CPOL 163.9K 58
Rate this:
Please Sign up or sign in to vote.
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Nish Nishant
United States United States
Nish Nishant is a Software Architect/Consultant based out of Columbus, Ohio. He has over 15 years of software industry experience in various roles including Lead Software Architect, Principal Software Engineer, and Product Manager. Nish is a recipient of the annual Microsoft Visual C++ MVP Award since 2002 (13 consecutive awards as of 2014).

Nish is an industry acknowledged expert in the Microsoft technology stack. He authored
C++/CLI in Action for Manning Publications in 2005, and had previously co-authored
Extending MFC Applications with the .NET Framework for Addison Wesley in 2003. In addition, he has over 140 published technology articles on CodeProject.com and another 250+ blog articles on his
WordPress blog. Nish is vastly experienced in team management, mentoring teams, and directing all stages of software development.

Contact Nish : You can reach Nish on his google email id voidnish.

Website and Blog

You may also be interested in...

Comments and Discussions

 
QuestionMessage Automatically Removed Pin
10-Mar-14 16:17
memberMember 1022658010-Mar-14 16:17 
GeneralMy vote of 5 Pin
manoj kumar choubey2-Mar-12 23:21
membermanoj kumar choubey2-Mar-12 23:21 
GeneralReason for using a counter instead of a boolean Pin
BardMorgan19-Jan-07 18:42
memberBardMorgan19-Jan-07 18:42 
Nish,

Very good article and quite useful.

I did modify the code slightly for my use. I eliminated the boolean once and replaced it with an int counter. I then exposed this as a property of the button.

In the timer Tick event handler, I increment the counter, instead of setting a boolean.

That allows me to handle things differently in the RepeatButton's click event depending on how long the button has been held down.

For example, I created a replacement NumericUpDown control (more as an experiment than anything) and if the button has been held down for less than 10 iterations, I increment/decrement the value by 1. For 11 to 20 iterations I increment/decrement by 5, and for over 20 iterations, I increment/decrement by 10. It helps when getting to large numbers since it accelerates.

I also reset the counter in the MouseUp event handler.

Thanks much,

Morgan
GeneralMake button appear as pressed Pin
SleepyBoBos22-May-06 14:30
memberSleepyBoBos22-May-06 14:30 
GeneralRe: Make button appear as pressed Pin
ricmil4225-Mar-07 8:20
memberricmil4225-Mar-07 8:20 
AnswerRe: Make button appear as pressed Pin
SleepyBoBos13-Apr-07 0:58
memberSleepyBoBos13-Apr-07 0:58 
Generalcan't get it to run Pin
xyzc21-Feb-05 7:42
memberxyzc21-Feb-05 7:42 
GeneralRe: can't get it to run Pin
Nishant S21-Feb-05 13:37
staffNishant S21-Feb-05 13:37 
QuestionWhat is once used for? Pin
Lorad11-Aug-03 8:25
memberLorad11-Aug-03 8:25 
AnswerRe: What is once used for? Pin
Nishant S11-Aug-03 17:22
editorNishant S11-Aug-03 17:22 
GeneralDear Nish, Pin
smastrus118-Apr-02 5:35
membersmastrus118-Apr-02 5:35 
GeneralRe: Dear Nish, Pin
Thomas George18-Apr-02 5:44
memberThomas George18-Apr-02 5:44 
GeneralRe: Dear Nish, Pin
Nish [BusterBoy]18-Apr-02 14:56
memberNish [BusterBoy]18-Apr-02 14:56 
GeneralRe: Dear Nish, Pin
Thomas George19-Apr-02 12:29
memberThomas George19-Apr-02 12:29 
GeneralRe: Dear Nish, Pin
Nish [BusterBoy]19-Apr-02 18:51
memberNish [BusterBoy]19-Apr-02 18:51 
GeneralRe: Dear Nish, Pin
Colin Davies19-Apr-02 19:11
memberColin Davies19-Apr-02 19:11 
GeneralRe: Dear Nish, Pin
Nish [BusterBoy]19-Apr-02 19:16
memberNish [BusterBoy]19-Apr-02 19:16 
GeneralRe: Dear Nish, Pin
Colin Davies19-Apr-02 19:35
memberColin Davies19-Apr-02 19:35 
GeneralRe: Dear Nish, Pin
Nish [BusterBoy]19-Apr-02 19:40
memberNish [BusterBoy]19-Apr-02 19:40 
GeneralRe: Dear Nish, Pin
Colin Davies19-Apr-02 19:49
memberColin Davies19-Apr-02 19:49 
GeneralRe: Dear Nish, Pin
Colin Davies19-Apr-02 20:10
memberColin Davies19-Apr-02 20:10 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150728.1 | Last Updated 17 Apr 2002
Article Copyright 2002 by Nish Nishant
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid