简体   繁体   中英

Long pressed button

I want to repeat an action when a Button is pressed during a long time, like for example the forward button of an MP3 reader. Is there an existing c# event in WinForm ?

I can handle the MouseDown event to start a timer which will perform the action and stop it on MouseUp event, but I am looking for an easier way to solve this problem => ie : a solution without a Timer (or Thread / Task ...).

UPDATED: Shortest way:

Using Anonymous Methods and Object Initializer :

public void Repeater(Button btn, int interval)
{
    var timer = new Timer {Interval = interval};
    timer.Tick += (sender, e) => DoProgress();
    btn.MouseDown += (sender, e) => timer.Start();
    btn.MouseUp += (sender, e) => timer.Stop();
    btn.Disposed += (sender, e) =>
                        {
                            timer.Stop();
                            timer.Dispose();
                        };
}

You can use timer between MouseDown and MouseUp.

MouseDownEvent

Timer tm1;

MouseUpEvent

Timer tm2;

You can easily handle them between two timers.

You will need to perform some action while the button is pressed, like skipping some seconds in the MP3-track.

Starting a timer that gets cancelled on mouseUp that triggers that kind of work on a regular interval (100ms?) while the button is down seems viable to me. Easy to implement and is non blocking on the UI.

A more simple solution will probably cause the UI to block.

I can handle the MouseDown event to start a timer which will perform the action and stop it on MouseUp event, but I am looking for an easier way to solve this problem .

You can make it easier by writing it once in a reusable way. You could derive your own Button class that has this behaviour.

Or write a class that you can attach to any button to give it this behaviour. For example you could do something like:

class ButtonClickRepeater
{
    public event EventHandler Click;

    private Button button;
    private Timer timer;

    public ButtonClickRepeater(Button button, int interval)
    {
        if (button == null) throw new ArgumentNullException();

        this.button = button;
        button.MouseDown += new MouseEventHandler(button_MouseDown);
        button.MouseUp += new MouseEventHandler(button_MouseUp);
        button.Disposed += new EventHandler(button_Disposed);

        timer = new Timer();
        timer.Interval = interval;
        timer.Tick += new EventHandler(timer_Tick);
    }

    void button_MouseDown(object sender, MouseEventArgs e)
    {
        OnClick(EventArgs.Empty);
        timer.Start();
    }

    void button_MouseUp(object sender, MouseEventArgs e)
    {
        timer.Stop();
    }

    void button_Disposed(object sender, EventArgs e)
    {
        timer.Stop();
        timer.Dispose();
    }

    void timer_Tick(object sender, EventArgs e)
    {
        OnClick(EventArgs.Empty);
    }

    protected void OnClick(EventArgs e)
    {
        if (Click != null) Click(button, e);
    }
}

You would then use it as follows:

private void Form1_Load(object sender, EventArgs e)
{
    ButtonClickRepeater repeater = new ButtonClickRepeater(this.myButton, 1000);
    repeater.Click += new EventHandler(repeater_Click);
}

or more concisely, since you don't need to keep a reference to ButtonClickRepeater :

private void Form1_Load(object sender, EventArgs e)
{
    new ButtonClickRepeater(this.myBbutton, 1000).Click += new EventHandler(repeater_Click);
}

shortest way (and without any task/thread/timer & stopwatch) :)

DateTime sw;
bool buttonUp = false;
const int holdButtonDuration = 2000;
private void btnTest_MouseDown(object sender, MouseEventArgs e)
{
    buttonUp = false;
    sw = DateTime.Now;
    while (e.Button == MouseButtons.Left && e.Clicks == 1 && (buttonUp == false && (DateTime.Now - sw).TotalMilliseconds < holdButtonDuration))
        Application.DoEvents();
    if ((DateTime.Now - sw).TotalMilliseconds < holdButtonDuration)
        Test_ShortClick();
    else
        Test_LongClick();
}
private void btnTest_MouseUp(object sender, MouseEventArgs e)
{
    buttonUp = true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM