Click here to Skip to main content
Click here to Skip to main content

.NET port of Joe's AutoRepeat Button class

, 16 Apr 2002
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)

About the Author

Nish Sivakumar

United States United States
Nish is a real nice guy who has been writing code since 1990 when he first got his hands on an 8088 with 640 KB RAM. Originally from sunny Trivandrum in India, he has been living in various places over the past few years and often thinks it’s time he settled down somewhere.
 
Nish has been a Microsoft Visual C++ MVP since October, 2002 - awfully nice of Microsoft, he thinks. He maintains an MVP tips and tricks web site - www.voidnish.com where you can find a consolidated list of his articles, writings and ideas on VC++, MFC, .NET and C++/CLI. Oh, and you might want to check out his blog on C++/CLI, MFC, .NET and a lot of other stuff - blog.voidnish.com.
 
Nish loves reading Science Fiction, P G Wodehouse and Agatha Christie, and also fancies himself to be a decent writer of sorts. He has authored a romantic comedy Summer Love and Some more Cricket as well as a programming book – Extending MFC applications with the .NET Framework.
 
Nish's latest book C++/CLI in Action published by Manning Publications is now available for purchase. You can read more about the book on his blog.
 
Despite his wife's attempts to get him into cooking, his best effort so far has been a badly done omelette. Some day, he hopes to be a good cook, and to cook a tasty dinner for his wife.

Comments and Discussions

 
QuestionMessage Automatically Removed PinmemberMember 1022658010-Mar-14 16:17 
GeneralMy vote of 5 Pinmembermanoj kumar choubey2-Mar-12 23:21 
GeneralReason for using a counter instead of a boolean PinmemberBardMorgan19-Jan-07 18:42 
GeneralMake button appear as pressed PinmemberSleepyBoBos22-May-06 14:30 
Firstly, thanks for the code.
 
Secondly, I notice after the initial click the button 'pops' up again I wonder how you would make the button appear to remain in the down state?
GeneralRe: Make button appear as pressed Pinmemberricmil4225-Mar-07 8:20 
AnswerRe: Make button appear as pressed PinmemberSleepyBoBos13-Apr-07 0:58 
Generalcan't get it to run Pinmemberxyzc21-Feb-05 7:42 
GeneralRe: can't get it to run PinstaffNishant S21-Feb-05 13:37 
QuestionWhat is once used for? PinmemberLorad11-Aug-03 8:25 
AnswerRe: What is once used for? PineditorNishant S11-Aug-03 17:22 
GeneralDear Nish, Pinmembersmastrus118-Apr-02 5:35 
GeneralRe: Dear Nish, PinmemberThomas George18-Apr-02 5:44 
GeneralRe: Dear Nish, PinmemberNish [BusterBoy]18-Apr-02 14:56 
GeneralRe: Dear Nish, PinmemberThomas George19-Apr-02 12:29 
GeneralRe: Dear Nish, PinmemberNish [BusterBoy]19-Apr-02 18:51 
GeneralRe: Dear Nish, PinmemberColin Davies19-Apr-02 19:11 
GeneralRe: Dear Nish, PinmemberNish [BusterBoy]19-Apr-02 19:16 
GeneralRe: Dear Nish, PinmemberColin Davies19-Apr-02 19:35 
GeneralRe: Dear Nish, PinmemberNish [BusterBoy]19-Apr-02 19:40 
GeneralRe: Dear Nish, PinmemberColin Davies19-Apr-02 19:49 
GeneralRe: Dear Nish, PinmemberColin 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 | Mobile
Web02 | 2.8.140721.1 | Last Updated 17 Apr 2002
Article Copyright 2002 by Nish Sivakumar
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid