【问题标题】:Doubleclicking a checkbox?双击复选框?
【发布时间】:2012-02-26 23:13:17
【问题描述】:

我有几个代表人的复选框。像这样的:

[ ] George
[ ] Sam
[ ] Steve
[ ] Lisa

每个都可以单独检查,当然也可以不检查。代码在检查状态更改时运行。该代码在其算法中使用所有复选框的状态。

但是,我希望它们在双击时也表现得像单选按钮。也就是说,如果你双击一个,它应该被选中(不管它之前的状态如何),而所有其他的都将被取消选中。

不幸的是,复选框没有双击事件。很明显,我需要通过使用 mousedown(或 mouse up)以及计时器、秒表等的组合来模拟双击。

最终我知道我会通过实验找到解决方案,所以如果我想出一个好的解决方案,我会在这里发布。但我有一种感觉,其他人之前有“模拟双击”,如果有人可以发布一个很好的 sn-p 来从 mousedown 事件创建这样的事件,那就太好了。

附: sn-p 应该以某种方式涉及SystmInformation.DoubleClickTime。 (这是区分双击和“两次单击”的毫秒数。它可能因一台机器与另一台机器不同。)单击的代码在经过这么长时间之前不应运行,以确保双击是'没有等待。 (因为正如我提到的,代码使用了所有复选框的状态。)

附言我正在将 VB.NET Express 2008 用于 winforms 应用程序,但如果需要,我可能可以翻译表单 C#,我认为这可能适用于所有 .NET 平台。

【问题讨论】:

  • 这是关于 WinForms、WPF、ASP.NET 的吗?
  • 对不起,winforms,我正在使用 VB.NET 我刚刚在我的问题中添加了一个 PPS。如果需要,我可以翻译 C# 解决方案。

标签: .net winforms checkbox double-click


【解决方案1】:

需要外科手术,编写 CheckBox 类以假定标准单击和双击行为已关闭。此代码有效,您将不得不放弃 MouseUp 事件:

Imports System.ComponentModel

Public Class MyCheckBox
    Inherits CheckBox

    Public Sub New()
        Me.SetStyle(ControlStyles.StandardClick Or ControlStyles.StandardDoubleClick, True)
    End Sub

    Protected Overrides Sub OnMouseUp(ByVal mevent As System.Windows.Forms.MouseEventArgs)
        '' NOTE: do *not* call the base method
        MyBase.ResetFlagsandPaint()
    End Sub

    <EditorBrowsable(EditorBrowsableState.Always), Browsable(True)> _
    Public Shadows Custom Event DoubleClick As EventHandler
        AddHandler(ByVal value As EventHandler)
            AddHandler MyBase.DoubleClick, value
        End AddHandler
        RemoveHandler(ByVal value As EventHandler)
            RemoveHandler MyBase.DoubleClick, value
        End RemoveHandler
        RaiseEvent(ByVal sender As Object, ByVal value As EventArgs)
            Throw New InvalidOperationException  '' should never be raised by user code
        End RaiseEvent
    End Event
End Class

事件处理程序可能如下所示:

Private Sub MyCheckBox_DoubleClick(ByVal sender As System.Object, ByVal e As System.EventArgs) _
    Handles MyCheckBox1.DoubleClick, MyCheckBox2.DoubleClick, MyCheckBox3.DoubleClick, MyCheckBox4.DoubleClick

    For Each box As CheckBox In GroupBox1.Controls
        box.Checked = box.Equals(sender)
    Next
End Sub

可能会有一些手术副作用,我没有看到任何副作用,但没有彻底测试。我建议您不要实际这样做,该功能在很大程度上是无法发现的。没有用户会意识到双击现在有什么特别的作用。

【讨论】:

  • 感谢您的回复,我正在调查提供的所有答案。我知道这是非标准行为,我有充分的理由。非常简单地说: 1) 非常需要一种只选择一个的方法,因为可能有 20 个预先选中的框。 2) 我正在替换具有类似行为的现有应用程序。 3)我将添加一个工具提示“双击以仅选择史蒂夫”。 4)添加新对象这样做会使屏幕混乱。 5) 这完全不会干扰标准行为。考虑例如:Ctrl-鼠标滚轮进行缩放。这是一个很多用户从未发现的很棒的功能,但那又如何呢?
  • 这是我要使用的,但要添加两个警告:首先,在 RaiseEvent 行中,我将 EventArgs 更改为 MouseEventArgs。其次,点击事件仍然过早触发......它应该等待 SystemInformation.DoubleClickTime 定义的时间段,以便在双击即将发生时不会触发点击。我相信大多数支持双击的对象都会出现这种延迟。 (按原样,在更改检查状态时运行的代码在双击时会出现两次,这并不理想。)我可以稍后处理这个小问题。谢谢汉斯和其他人。
【解决方案2】:

复选框确实有一个 DoubleClick 事件。

CheckBox Class

DoubleClick 基础设施。当用户双击 CheckBox 时发生 控制。

编辑

如 cmets 中所述,默认行为是不调用事件。

不过,您可以做的是创建自己的继承自 CheckBox 的类。
您需要设置 StandardDoubleClick 样式。使用 SetStyle() 方法。
然后重写 OnDoubleClick 方法以在事件引发之前捕获它。

public class MyCheckBox : CheckBox {

 MyCheckBox()
 {
    this.SetStyle(ControlStyles.StandardDoubleClick);
 }


 protected override void OnDoubleClick(EventArgs e)
 {
   Base.OnDoubleClick(e);
   //Do what ever you want... Like actually calling the DoubleClick event....
 }

}

【讨论】:

  • 抱歉,我编辑了我的问题以澄清我正在使用 VB.NET 2008 Express,其中肯定没有复选框的双击事件。
  • 它仍然是 .Net 框架……DoubleClick 事件自 .Net 1.1 以来一直存在……也许它不在设计器中,但它就在那里。
  • Hmmm... 这个关于复选框(框架 3.5)的双击事件的页面说“StandardClick 和 StandardDoubleClick 枚举默认设置为 false”,这意味着它存在,但没有引发:@ 987654326@我怎样才能让事件被提出?
  • @Paul :你说得对,默认情况下它是禁用的。您可以从该类继承,并使用 OnEvent 捕获它......我已经用一个示例编辑了我的答案
  • @Paul:可以使用 SetStyle() 设置枚举
【解决方案3】:
您可以使用 MouseDoubleClick,但该事件不会通过 Design 接口公开。要使用它,将以下行添加到构造函数或表单的加载事件中: checkBox1.MouseDoubleClick += new MouseEventHandler(checkBox1_MouseDoubleClick); 这假定一个 checkBox1.MouseDoubleClick 方法,如下所示: void checkBox1_MouseDoubleClick(对象发送者,MouseEventArgs e) { 抛出新的 NotImplementedException(); }


好的,最后一个例子不起作用,你是对的; DoubleClick 事件永远不会引发。所以,这可能有点“hacky”,但会起作用:

扩展CheckBox 类,例如创建一个CheckboxExtended 类。在这个类中,我们重写了WndProc 方法并拦截windows 双击消息。示例代码如下:

public class CheckBoxExtended : CheckBox
{
    private const int WM_LBUTTONDBLCLK = 0x203;

    protected override void WndProc(ref Message m)
    {
        // Threat the message first
        if (m.Msg == WM_LBUTTONDBLCLK)
        {
            var lparam = m.LParam.ToInt32();
            var x = lparam & 0x0000FFFF;
            var y = (int) ((lparam & 0xFFFF0000) >> 16);

            OnMouseDoubleClick(new MouseEventArgs(MouseButtons.Left, 2, x, y, 0));
        }

        base.WndProc(ref m);
    }
}

我仍然不确定解析 LParam 以获得鼠标位置。请给我几秒钟的时间。

要使用这个类,就像我之前说的那样做:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        checkBoxExtended1.MouseDoubleClick += new MouseEventHandler(checkBoxExtended1_MouseDoubleClick);
    }

    void checkBoxExtended1_MouseDoubleClick(object sender, MouseEventArgs e)
    {
        MessageBox.Show(@"Test");
    }

}

当然,我假设一个带有CheckBoxExtended 的表单。

编辑:哎呀,我刚刚发现我使用的是二进制文件或而不是二进制文件和。现在源是固定的,应该返回正确的坐标。

编辑 2: 好的,我已经在 VB 中创建了这个类,但我还没有测试过——我在 VB 中的技能也不是很好。一个提示:您可以自己为扩展类编写另一个 DoubleClick 事件,并添加必要的装饰(属性)以使设计器能够显示它。

Public Class CheckboxExtended
    Inherits CheckBox

    Private Const WM_LBUTTONDBLCLK As Integer = &H203

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)

        'Threat the message first
        If m.Msg = WM_LBUTTONDBLCLK Then

            Dim lparam = m.LParam.ToInt32()
            Dim x = lparam And &HFFFF
            Dim y = ((lparam And &HFFFF0000) >> 16)

            OnMouseDoubleClick(New MouseEventArgs(MouseButtons.Left, 2, x, y, 0))
        End If

        MyBase.WndProc(m)
    End Sub
End Class

【讨论】:

  • 哎呀。这诱使我只使用标签(具有讽刺意味的是确实暴露了双击)并在它旁边放一个小方块,我可以检查代码,以便它“看起来”检查。大声笑-我实际上不会这样做,但我想到了。此外,您的解决方案似乎不会在您的解决方案中延迟“单次”点击事件。 (正如我所提到的,最好单击一次不运行代码几毫秒,直到我们确定不会发生双击。)我可能弄错了,但我相信通常暴露双击的对象会延迟单击事件(不知不觉)正是因为这个原因。
  • @Paul,这也是我的猜测。 Windows 有延迟考虑双击,这实际上是可配置的(控制面板上鼠标配置菜单中的“双击速度”)。这个解决方案也说明了这一点,因为我们要让窗口负责。
  • 您的解决方案似乎与 Yochai 的解决方案大致相同,只是他(或她)使用 SetStyle 设置 StandardDoubleClick 枚举。虽然我确实声称我可以从 C# 翻译,(而且我通常可以)我仍然是一个 VB 人,在这种情况下,我可能没有我想象的那么聪明。如果您可以对此进行 VB 化,那将会很有帮助。
  • @Paul:修复了坐标的来源。我将尝试将其编写为 VB 代码。
  • @Paul:添加了 VB 示例。看看它是否运行正常,否则再次在这里发布,我会尝试解决它可能遇到的任何问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-16
  • 2017-02-11
  • 1970-01-01
相关资源
最近更新 更多