Click here to Skip to main content
15,867,568 members
Articles / Programming Languages / C#
Article

.NET port of Joe's AutoRepeat Button class

Rate me:
Please Sign up or sign in to vote.
4.86/5 (37 votes)
16 Apr 2002CPOL4 min read 189.6K   58   22
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

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


Written By
United States United States
Nish Nishant is a technology enthusiast from Columbus, Ohio. He has over 20 years of software industry experience in various roles including Chief Technology Officer, Senior Solution Architect, Lead Software Architect, Principal Software Engineer, and Engineering/Architecture Team Leader. Nish is a 14-time recipient of the Microsoft Visual C++ MVP Award.

Nish authored C++/CLI in Action for Manning Publications in 2005, and 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 experienced in technology leadership, solution architecture, software architecture, cloud development (AWS and Azure), REST services, software engineering best practices, CI/CD, mentoring, and directing all stages of software development.

Nish's Technology Blog : voidnish.wordpress.com

Comments and Discussions

 
GeneralMy vote of 5 Pin
Manoj Kumar Choubey2-Mar-12 23:21
professionalManoj Kumar Choubey2-Mar-12 23:21 
GeneralReason for using a counter instead of a boolean Pin
BardMorgan19-Jan-07 18:42
BardMorgan19-Jan-07 18:42 
GeneralMake button appear as pressed Pin
SleepyBoBos22-May-06 14:30
SleepyBoBos22-May-06 14:30 
GeneralRe: Make button appear as pressed Pin
ricmil4225-Mar-07 8:20
ricmil4225-Mar-07 8:20 
AnswerRe: Make button appear as pressed Pin
SleepyBoBos13-Apr-07 0:58
SleepyBoBos13-Apr-07 0:58 
Generalcan't get it to run Pin
bekiser21-Feb-05 7:42
bekiser21-Feb-05 7:42 
GeneralRe: can't get it to run Pin
Nish Nishant21-Feb-05 13:37
sitebuilderNish Nishant21-Feb-05 13:37 
QuestionWhat is once used for? Pin
Jeff Lindholm11-Aug-03 8:25
Jeff Lindholm11-Aug-03 8:25 
AnswerRe: What is once used for? Pin
Nish Nishant11-Aug-03 17:22
sitebuilderNish Nishant11-Aug-03 17:22 
GeneralDear Nish, Pin
smastrus118-Apr-02 5:35
smastrus118-Apr-02 5:35 
GeneralRe: Dear Nish, Pin
User 988518-Apr-02 5:44
User 988518-Apr-02 5:44 
also, when dreaming why limit to 19". dream big!!

Smile | :) Smile | :)

Thomas

modified 29-Aug-18 21:01pm.

GeneralRe: Dear Nish, Pin
Nish Nishant18-Apr-02 14:56
sitebuilderNish Nishant18-Apr-02 14:56 
GeneralRe: Dear Nish, Pin
User 988519-Apr-02 12:29
User 988519-Apr-02 12:29 
GeneralRe: Dear Nish, Pin
Nish Nishant19-Apr-02 18:51
sitebuilderNish Nishant19-Apr-02 18:51 
GeneralRe: Dear Nish, Pin
ColinDavies19-Apr-02 19:11
ColinDavies19-Apr-02 19:11 
GeneralRe: Dear Nish, Pin
Nish Nishant19-Apr-02 19:16
sitebuilderNish Nishant19-Apr-02 19:16 
GeneralRe: Dear Nish, Pin
ColinDavies19-Apr-02 19:35
ColinDavies19-Apr-02 19:35 
GeneralRe: Dear Nish, Pin
Nish Nishant19-Apr-02 19:40
sitebuilderNish Nishant19-Apr-02 19:40 
GeneralRe: Dear Nish, Pin
ColinDavies19-Apr-02 19:49
ColinDavies19-Apr-02 19:49 
GeneralRe: Dear Nish, Pin
ColinDavies19-Apr-02 20:10
ColinDavies19-Apr-02 20:10 

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

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