长按按钮

7
我想在长时间按下一个按钮时重复执行某个操作,比如 MP3 播放器的向前按钮。在 WinForm 中是否存在此类 c# 事件?
我可以处理 MouseDown 事件以启动定时器执行操作,并在 MouseUp 事件上停止它,但我正在寻找一种更简单的解决方法,即:无需使用 Timer(或线程 / 任务等)的解决方案。
5个回答

8

更新:最简单的方法:

使用匿名方法对象初始化器

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();
                        };
}

最好在鼠标松开时取消Tick事件的订阅。 - g t
也不要忘记释放计时器。 - Joe
你正在使用一个 Timer,而匿名方法只是一种比编写真正的方法更短的方式。这在 Framework 4.0 中不存在吗? - Emmanuel Chaffraix

1

最短的方法(无需任何任务/线程/计时器和秒表):)

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;
}

秒表类是一个计时器!目前还没有在框架端处理定时器/任务/线程的解决方案。 - Emmanuel Chaffraix
最短的方式(不涉及任何任务/线程/定时器和秒表) :) - Ersin Kecis

0
你可以在MouseDown和MouseUp之间使用计时器。
MouseDownEvent

Timer tm1;

MouseUpEvent

Timer tm2;

你可以在两个计时器之间轻松处理它们。


0
我可以处理MouseDown事件来启动一个计时器,该计时器将执行操作,并在MouseUp事件上停止它,但我正在寻找解决这个问题的更简单的方法。
你可以通过以可重用的方式编写一次来使其更简单。你可以派生自己的Button类,具有这种行为。
或者编写一个可以附加到任何按钮的类,赋予它这种行为。例如,你可以做如下操作:
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);
    }
}

然后您可以按以下方式使用它:

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

更简洁地说,因为您不需要保留对 ButtonClickRepeater 的引用:
private void Form1_Load(object sender, EventArgs e)
{
    new ButtonClickRepeater(this.myBbutton, 1000).Click += new EventHandler(repeater_Click);
}

0

当按钮被按下时,您需要执行一些操作,例如跳过MP3曲目中的几秒钟。

启动一个计时器,在鼠标抬起时取消它,触发在按钮按下时以固定间隔(100ms?)进行的工作似乎是可行的。易于实现,并且不会阻塞UI。

更简单的解决方案可能会导致UI阻塞。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接