2011-01-27 125 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之間運行點擊事件。