2011-01-27 186 views
7

我有一种情况,我正在处理一个窗体上的双击鼠标单击事件&。在这两种情况下都必须加载,但是当发生双击时,我不希望执行附加到单击事件的代码。拦截单击或双击鼠标 - 仅执行双击代码双击

有没有办法拦截鼠标点击,并检查双或单,然后适当地执行正确的事件?

也许通过拦截窗口的WndProc或者什么?

+0

这是WinForms还是WPF? – ChrisF 2011-01-27 09:32:56

+0

这是WinForms – 2011-01-27 09:33:15

回答

6

不,这几乎是不可能的,除非你有时间机器。一旦您了解了Windows如何区分双击和单击,它并没有什么意义。

事实证明,Raymond Chen(Windows Shell团队的开发人员)在标题为“Logical consequences of the way Windows converts single-clicks into double-clicks”的博客中解释了这一点。

具体而言,Windows只知道将某些内容解释为双击,因为在GetDoubleClickTime function指定的时间间隔内发生了秒的点击。因为需要千里眼(正如雷蒙德如此雄辩地说),以确定前面的时间,如果事情将是单击或双击,窗口管理器继续并在收到第一次点击后发送WM_LBUTTONDOWN messageWM_LBUTTONDBLCLK message仅在稍后发送,在第二次点击确认后实际表示双击。结果是,您的应用程序将始终收到两个WM_LBUTTONDOWN消息收到的每个WM_LBUTTONDBLCLK消息。

现在,.NET Framework设计人员了解此过程如何工作并设计了相应引发的事件。当然,他们不能对双击之前始终发生的单击操作做任何事情,但是如果确定用户希望成为双击事件的一部分,他们就能够抑制第二次点击消息。作为Control.MouseClick event的文件(这大致对应于WM_LBUTTONDOWN消息)告诉我们:发生在时间上足够接近,如由用户操作系统的鼠标设置确定

两个单点击,将生成一个MouseDoubleClick事件而不是第二次MouseClick事件。

,我挂上面确实,但是,提出了应用和开发谁坚持设计一个可能的解决方法雷蒙德的博客文章,其中的双击动作是无关的单单击操作(虽然我们都不建议你实际上做到这一点):

现在假设你是一个程序,但仍想继续双击操作与单击操作无关的可疑设计。你是做什么?

那么,你可以做的一件事就是在收到WM_LBUTTONDOWN消息时不做任何事情,除了设置一个定时器在GetDoubleClickTime()毫秒内触发。 [已更正上午10点]如果在此时间内收到WM_LBUTTONDBLCLK消息,则最终是双击。如果你不这样做,那么它一定是单击,所以你可以做你的单击动作(虽然有点晚)。

+0

我删除了我的答案,因为我完全错过了问题的要点。 – ChrisF 2011-01-27 09:48:55

4

这里是做你要求的代码。

Public Class Form1 
    Const WM_LBUTTONDOWN As Integer = &H201 
    Const WM_LBUTTONDBLCLK As Integer = &H203 

    Private WithEvents tmrDoubleClicks As Timer 

    Dim isDblClk As Boolean 
    Dim firstClickTime As Date 
    Dim doubleClickInterval As Integer 

    Sub New() 

     ' This call is required by the designer. 
     InitializeComponent() 
     tmrDoubleClicks = New Timer 

     ' Add any initialization after the InitializeComponent() call. 
     tmrDoubleClicks.Interval = 50 
     doubleClickInterval = CInt(Val(Microsoft.Win32.Registry.CurrentUser. 
             OpenSubKey("Control Panel\Mouse"). 
             GetValue("DoubleClickSpeed", 1000))) 
    End Sub 

    Protected Overrides Sub Dispose(ByVal disposing As Boolean) 
     Try 
      If disposing AndAlso components IsNot Nothing Then 
       components.Dispose() 
      End If 
      If disposing AndAlso tmrDoubleClicks IsNot Nothing Then 
       tmrDoubleClicks.Dispose() 
      End If 
     Finally 
      MyBase.Dispose(disposing) 
     End Try 
    End Sub 

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) 
     Select Case m.Msg 
      Case WM_LBUTTONDOWN 
       If Not isDblClk Then 
        firstClickTime = Now 
        tmrDoubleClicks.Start() 
       End If 

      Case WM_LBUTTONDBLCLK 
       isDblClk = True 
       tmrDoubleClicks.Stop() 
       DoubleClickActivity() 
       isDblClk = False 

      Case Else 
       MyBase.WndProc(m) 
     End Select 
    End Sub 

    Private Sub DoubleClickActivity() 
     'implement double click activity here 
     Dim r As New Random(Now.TimeOfDay.Seconds) 
     Me.BackColor = Color.FromArgb(r.Next(0, 255), 
             r.Next(0, 255), 
             r.Next(0, 255)) 
    End Sub 

    Private Sub SingleClickActivity() 
     'implement single click activity here 
     Beep() 
    End Sub 

    Private Sub tmrDoubleClicks_Tick(ByVal sender As Object, 
            ByVal e As System.EventArgs 
            ) Handles tmrDoubleClicks.Tick 

     If Now.Subtract(firstClickTime).TotalMilliseconds > 
      doubleClickInterval Then 

      'since there was no other click within the doubleclick speed, 
      'stop waiting and fire the single click activity 
      isDblClk = False 
      tmrDoubleClicks.Stop() 
      SingleClickActivity() 
     End If 
    End Sub 
End Class 

此代码的症结在于延迟触发点击事件,直到双击时间过去。如果在该时间内,则在该时间内发生另一个点击事件,双击事件被调用而不调用点击事件。但是,如果没有双击,则会调用点击事件。

这种延迟在具有较长双击速度的计算机上尤为明显。在典型的计算机上,双击速度为500ms,因此代码会在点击发生后的500ms到600ms之间运行点击事件。