Single or double-click interception - only double-click on double-click

I have a situation where I process both single and double mouse click events in a form. In both cases, something needs to be loaded, but when I double-click, I don’t want to execute the code attached to the event with one click.

Is there a way to capture a mouse click and check if it is double or single, and then properly execute the correct event?

Perhaps intercepting WndProc windows or something else?

+7
source share
2 answers

No, it is almost impossible if you do not have a time machine. And that doesn't even make sense as soon as you understand how Windows selects double clicks with a single click.

Turns out Raymond Chen (the developer of the Windows Shell team) explains exactly this in a blog post titled "The logical implications of how Windows converts single-click double-clicks ."

In particular, Windows only knows to interpret something as a double click because the second click occurred during the interval specified by the GetDoubleClickTime function. Since it will require clairvoyance (as Raymond so eloquently expresses it) to determine in advance whether something will be a single or double-click, the window manager will continue and send WM_LBUTTONDOWN as soon as the first click is received. The WM_LBUTTONDBLCLK message is sent later, after confirming the second click, it is actually a double click. The result is that your application will always receive two WM_LBUTTONDOWN messages for each received WM_LBUTTONDBLCLK message.

Now, the developers of the .NET Framework have understood how this process works and developed the appropriate events. Of course, they cannot do anything with a single click, which always happens before a double click, but they can suppress a second click message if it is determined that the user intended to be part of the double click event. Since the documentation for the Control.MouseClick event (which roughly corresponds to the WM_LBUTTONDOWN message) tells us:

Two separate clicks that are close enough in time, as determined by the mouse settings in the user operating system, generate the MouseDoubleClick event instead of the second MouseClick event.

The Raymond blog article I linked to above, however, offers a possible workaround for apps and developers who insist on a design where the double-click action is not related to the one-click action (although none of us recommends you actually actually do it):

Now suppose you are a program that, nevertheless, wants to continue the dubious development of the fact that the double-click action is not related to the one-click action. What are you doing?

Well, one thing you could do is do nothing when you receive the WM_LBUTTONDOWN message, except for the given timer to start in GetDoubleClickTime() milliseconds. [Fixed 10am.] If you received WM_LBUTTONDBLCLK message during this time, then that was a double click. If you do not, then it was one click away, so you can do a one-time action (albeit a little late).

+6
source

Here is the code you are doing.

 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 

The essence of this code is to delay the click event until the double-click time expires. If during this time another click event occurs, a double-click event is raised without calling the click event. If, however, there is no double-click, the click event is fired.

This delay is especially noticeable on computers with higher double-click speeds. On a typical computer, the double-click speed is 500 ms, so the code fires a click event somewhere between 500 ms and 600 ms after the click occurs.

+4
source

All Articles