如何在 .NET 单选按钮中获取 DoubleClick 事件?

问题描述 投票:0回答:5

我希望能够从标准 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 )将是显而易见的解决方案,但我们没有这样的奢侈。

.net winforms radio-button double-click
5个回答
11
投票

根据您最初的建议,我提出了一个解决方案,无需使用反射对单选按钮进行子类化:

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。


3
投票

你可以这样做:

myRadioButton.MouseClick += new MouseEventHandler(myRadioButton_MouseClick);

void myRadioButton_MouseClick(object sender, MouseEventArgs e)
{
    if (e.Clicks == 2)
    {
         // Do something
    }
}

您可能也可能不想检查 e.Button == MouseButtons.Left


1
投票

根据@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());

0
投票

抱歉,没有资格对此发表评论。您试图让用户双击执行什么操作?我认为使用双击可能会令人困惑,因为它与用户对单选按钮的一般心理模型不同(即单击,从一组中选择一个选项)


0
投票

这可能不像发布时那样相关,但仍然有这样的选项。

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();
}
© www.soinside.com 2019 - 2024. All rights reserved.