10 分钟内实现自动重复按钮






4.68/5 (24投票s)
简单的 WinForms 自动重复按钮,几行代码即可完成
引言
你是否曾需要一个按钮,能够模仿键盘的自动重复行为?也就是说,当按钮被点击并按住时,只要按钮被按下,它就会发出一个 MouseDown
事件序列。
我的程序需要这样一个按钮。照例,我开始在CodeProject上搜索,并找到了一个有趣的帖子 Joe 的自动重复按钮类的 .NET 移植版,作者是 Nish Sivakumar。提出的代码完成了它的任务,我正准备将其复制并粘贴到我的项目中,这时我意识到,我可以用更简单的逻辑和更少的代码来实现所需的功能。
背景
基本思路与原文章相同:使用一个定时器控件周期性地执行代码,模拟按住按钮时的多次 MouseDown
事件。
代码
既然我承诺实现起来简单快捷,那么我们就开始吧。
首先,我创建了一个继承自 Button
的 RepeatButton
用户控件。
public class RepeatButton : Button
其次,我添加了一个 Timer
控件,并将其重命名为 timerRepeater
。首先,我添加了一个空的 tick 事件处理程序
private void timerRepeater_Tick(object sender, EventArgs e)
{
//Will be coded later
}
第三,我定义了两个新属性来控制重复时序
[DefaultValue(400)]
public int InitialDelay { set; get; }
[DefaultValue(62)]
public int RepeatInterval { set; get; }
我确保了属性在构造函数中得到正确初始化
public RepeatButton():base()
{
InitializeComponent();
InitialDelay = 400;
RepeatInterval = 62;
}
接下来,我重写了 OnMouseDown
事件处理程序。新代码做了三件事
- 它将事件参数保存到一个外部变量。这是必需的,因为事件实际上将由
timerRepeat_Tick
事件处理程序处理,而该处理程序需要这些信息。 - 它确保
timerRepeater
是禁用的。这行代码实际上不是必需的,因为在执行OnMouseDown
时timerRepeater
总是被禁用的。我在这里添加它是为了代码的清晰性。 - 它调用
timerRepeater_Tick
,该调用将立即处理初始单击以及在鼠标按住期间的所有重复。
MouseEventArgs MouseDownArgs = null;
protected override void OnMouseDown(MouseEventArgs mevent)
{
MouseDownArgs = mevent;
timerRepeater.Enabled = false;
timerRepeater_Tick(null, EventArgs.Empty);
}
最后,代码的关键部分,也就是重复循环发生的地方。是时候为 timerRepeater_Tick
填充可用代码了。
当用户按下按钮时,从 OnMouseDown
中显式调用此处理程序。第一行包含对 base.OnMouseDown
的调用。这是实际处理 MouseDown
事件的地方,也是将控件宿主的代码通知鼠标已被按下的地方。
下一篇
如果 timerRepeater
未启用(当 timerRepeater_Tick
从 OnMouseDown
调用时,它从未启用),这意味着这是在按下鼠标后第一次调用此代码。在这种情况下,timerRepeater.Interval
被设置为 InitialDelay
,否则它被设置为 RepeatInterval
。
最后一行代码,将 timerRepeater.Enabled
属性设置为 true
。这将导致 timerRepeater_Tick
以 Interval
属性中设置的时间间隔持续调用。
private void timerRepeater_Tick(object sender, EventArgs e)
{
base.OnMouseDown(MouseDownArgs);
if (timerRepeater.Enabled)
timerRepeater.Interval = RepeatInterval;
else
timerRepeater.Interval = InitialDelay;
timerRepeater.Enabled = true;
}
上述代码将在鼠标初始按下后永远被调用。我们需要在鼠标再次抬起时停止此行为。没有比这更简单的了。在 OnMouseUp
中需要额外的一行代码,将 timerRepeater.Enabled
属性设置为 false
。这将立即停止 timerRepeater_Tick
循环。
protected override void OnMouseUp(MouseEventArgs mevent)
{
base.OnMouseUp(mevent);
timerRepeater.Enabled = false;
}
好了,这就是完整的、功能性的 RepeatButton
,可能用时甚至不到 10 分钟。
RepeatButton
的全部代码如下所示,您可以将其复制并粘贴到您的解决方案中
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;
namespace RepeatButtonControl
{
public class RepeatButton : Button
{
private Timer timerRepeater;
private IContainer components;
public RepeatButton():base()
{
InitializeComponent();
InitialDelay = 400;
RepeatInterval = 62;
}
[DefaultValue(400)]
public int InitialDelay { set; get; }
[DefaultValue(62)]
public int RepeatInterval { set; get; }
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.timerRepeater = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
this.timerRepeater.Tick += new System.EventHandler(this.timerRepeater_Tick);
this.ResumeLayout(false);
}
MouseEventArgs MouseDownArgs = null;
protected override void OnMouseDown(MouseEventArgs mevent)
{
//Save arguments
MouseDownArgs = mevent;
timerRepeater.Enabled = false;
timerRepeater_Tick(null, EventArgs.Empty);
}
private void timerRepeater_Tick(object sender, EventArgs e)
{
base.OnMouseDown(MouseDownArgs);
if (timerRepeater.Enabled)
timerRepeater.Interval = RepeatInterval;
else
timerRepeater.Interval = InitialDelay;
timerRepeater.Enabled = true;
}
protected override void OnMouseUp(MouseEventArgs mevent)
{
base.OnMouseUp(mevent);
timerRepeater.Enabled = false;
}
}
}
Using the Code
您可以跟着代码,重复文章中描述的所有步骤,从头开始开发一个重复按钮,这很容易也很有趣。
如果您想节省时间,也可以下载附带的源代码。它包含 RepeatButton
的源代码和一个演示应用程序,说明了重复按钮的行为。无需过多解释。
您在演示主屏幕上按下 repeatButton
,按住它,然后观察事件的生成情况,如下面的屏幕截图所示
可下载的 zip 文件还包含帮助文件 (chm)。请注意,由于您是从互联网下载此文件,为了使用它,您必须先取消阻止。您可以在 Windows 资源管理器中执行此操作:右键单击帮助文件,选择“**属性**”,然后单击“**取消阻止**”按钮。
历史
- 2013年8月1日 - 初始发布
- 2013年9月17日 - 更新了源代码:改进了样式,添加了注释,添加了
Dispose
方法,为控件添加了帮助文件 (chm) - 2013年12月13日 - 对文章文本进行了小幅改进