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

发布于 2024-07-26 00:05:59 字数 1234 浏览 4 评论 0原文

我希望能够从标准 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 的帖子 这里,双击单选按钮的能力(如果这些是对话框上的唯一控件)使对话框变得很小对于了解它的人来说更容易使用。

在 Vista 中使用任务对话框(请参阅此 Microsoft 指南页面此专门关于任务对话框 API 的 MSDN 页面)将是显而易见的解决方案,但我们没有这样的奢侈。

I'd like to be able to catch the DoubleClick or MouseDoubleClick events from a standard winforms radio button, but they seem to be hidden and not working. At the moment I have code like this:

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

Is there a simpler and cleaner way to do it?

Edit: For background, I agree with Raymond Chen's post here that the ability to double click on a radio button (if those are the only controls on the dialog) makes the dialog just a tiny bit easier to use for people who know about it.

In Vista using Task Dialogs (see this Microsoft guideline page or this MSDN page specifically about the Task Dialog API) would be the obvious solution, but we don't have the luxury of that.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

〃温暖了心ぐ 2024-08-02 00:05:59

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

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。

Based on your original suggestion I made a solution without the need to subclass the radiobuton using reflection:

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;

Now the double click event for the radiobutton is fired.
BTW: The suggestion of Nate using e.Clicks doesn't work. In my tests e.Clicks was always 1 no matter how fast or often I clicked the radiobutton.

万人眼中万个我 2024-08-02 00:05:59

你可以这样做:

myRadioButton.MouseClick += new MouseEventHandler(myRadioButton_MouseClick);

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

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

You could do something like this:

myRadioButton.MouseClick += new MouseEventHandler(myRadioButton_MouseClick);

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

You may or may not also want to check that e.Button == MouseButtons.Left

套路撩心 2024-08-02 00:05:59

基于@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());

Based on @MSW answer, I made this extension class:

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

Which is then super easy to set up and re-use:

radioButton.AllowDoubleClick((a, b) => myDoubleClickAction());
記柔刀 2024-08-02 00:05:59

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

Sorry, don't have the reputation to comment on this. What action are you trying to have the double-click perform for the user? I think using a double-click may be confusing because it is different from the general mental model that a user has of a radio-button (IE single click, select one option from a set)

慕巷 2024-08-02 00:05:59

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

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

This is probably not as relevant as it was at the time of release, but there is still such an option.

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
}

It looks a bit bulky, but it allows to detect double clicks without using reflection, so it is actually a lightweight object. Also, it can be rewritten as a non-component class for further optimization.

It can be used in a simple way with some constants to specify controls.

private void radioButtonYes_MouseUp(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left && doubleClickDetectorMain.Detect(0, e.X, e.Y)) buttonOk.PerformClick();
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文