我希望能够从标准 winforms 单选按钮捕获 DoubleClick 或 MouseDoubleClick 事件,但它们似乎是隐藏的并且不起作用。目前我有这样的代码:
public class RadioButtonWithDoubleClick : RadioButton
{
public RadioButtonWithDoubleClick()
: base()
{
this.SetStyle( ControlStyles.StandardClick | ControlStyles.StandardDoubleClick, true );
}
[EditorBrowsable( EditorBrowsableState.Always ), Browsable( true )]
public new event MouseEventHandler MouseDoubleClick;
protected override void OnMouseDoubleClick( MouseEventArgs e )
{
MouseEventHandler temp = MouseDoubleClick;
if( temp != null ) {
temp( this, e );
}
}
}
有没有更简单、更干净的方法?
编辑:作为背景,我同意 Raymond Chen 的帖子here,即双击单选按钮的能力(如果这些是对话框上的only控件)使对话框更易于人们使用谁知道呢。
在 Vista 中,使用任务对话框(请参阅 此 Microsoft 指南页面 或 此 MSDN 页面专门介绍任务对话框 API )将是显而易见的解决方案,但我们没有这样的奢侈。
根据您最初的建议,我提出了一个解决方案,无需使用反射对单选按钮进行子类化:
MethodInfo m = typeof(RadioButton).GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic);
if (m != null)
{
m.Invoke(radioButton1, new object[] { ControlStyles.StandardClick | ControlStyles.StandardDoubleClick, true });
}
radioButton1.MouseDoubleClick += radioButton1_MouseDoubleClick;
现在单选按钮的双击事件被触发。 顺便说一句:Nate 使用 e.Clicks 的建议不起作用。在我的测试中,无论我单击单选按钮的速度有多快或多频繁,e.Clicks 始终为 1。
你可以这样做:
myRadioButton.MouseClick += new MouseEventHandler(myRadioButton_MouseClick);
void myRadioButton_MouseClick(object sender, MouseEventArgs e)
{
if (e.Clicks == 2)
{
// Do something
}
}
您可能也可能不想检查 e.Button == MouseButtons.Left
根据@MSW的回答,我做了这个扩展类:
static class RadioButtonEx
{
public static void AllowDoubleClick(this RadioButton rb, MouseEventHandler MouseDoubleClick)
{
//
// Allow double clicking of radios
System.Reflection.MethodInfo m = typeof(RadioButton).GetMethod("SetStyle", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
if (m != null)
m.Invoke(rb, new object[] { ControlStyles.StandardClick | ControlStyles.StandardDoubleClick, true });
rb.MouseDoubleClick += MouseDoubleClick;
}
}
这非常容易设置和重复使用:
radioButton.AllowDoubleClick((a, b) => myDoubleClickAction());
抱歉,没有资格对此发表评论。您试图让用户双击执行什么操作?我认为使用双击可能会令人困惑,因为它与用户对单选按钮的一般心理模型不同(即单击,从一组中选择一个选项)
这可能不像发布时那样相关,但仍然有这样的选项。
public partial class DoubleClickDetector : Component
{
#region Public Fields
public const int UnknownId = int.MinValue;
#endregion Public Fields
#region Private Fields
private readonly Stopwatch stopwatch = Stopwatch.StartNew();
private int lastId = UnknownId;
private long lastMS;
private int lastX;
private int lastY;
#endregion Private Fields
#region Public Constructors
public DoubleClickDetector() => InitializeComponent();
public DoubleClickDetector(IContainer container)
{
container.Add(this);
InitializeComponent();
}
#endregion Public Constructors
#region Public Methods
public bool Detect(int id, int x, int y)
{
long elapsedMS = stopwatch.ElapsedMilliseconds;
bool isDouble = id != UnknownId && lastId == id && elapsedMS - lastMS <= SystemInformation.DoubleClickTime &&
Math.Abs(lastX - x) <= SystemInformation.DoubleClickSize.Width &&
Math.Abs(lastY - y) <= SystemInformation.DoubleClickSize.Height;
lastId = isDouble ? UnknownId : id;
lastMS = elapsedMS;
lastX = x;
lastY = y;
return isDouble;
}
#endregion Public Methods
}
它看起来有点笨重,但它允许在不使用反射的情况下检测双击,所以它实际上是一个轻量级的对象。另外,还可以将其重写为非组件类以进一步优化。
可以通过简单的方式使用一些常量来指定控件。
private void radioButtonYes_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && doubleClickDetectorMain.Detect(0, e.X, e.Y)) buttonOk.PerformClick();
}