检测两个WM_LBUTTONUP消息之间经过的时间,以确定WM_LBUTTONDBLCLK

时间:2014-09-25 19:48:18

标签: .net vb.net winforms hook pinvoke

我正在尝试编写一个LL-MouseHook来截取应用程序的点击,我在其他网站上看到的研究似乎WM_LBUTTONDBLCLK消息无法正常处理,我不确定为什么,而且MSDN文档没有将此消息列为使用此类钩子进行处理的其中一个方法,如下面的引文中所示:

http://msdn.microsoft.com/en-us/library/windows/desktop/ms644986%28v=vs.85%29.aspx

  

输入:WPARAM

     

鼠标消息的标识符。

     

此参数可以是以下消息之一:

     

WM_LBUTTONDOWN,WM_LBUTTONUP,WM_MOUSEMOVE,WM_MOUSEWHEEL,WM_MOUSEHWHEEL,WM_RBUTTONDOWN或WM_RBUTTONUP。

无论如何我不确定列表是否非常可靠,因为中间的按钮没有列在那里, CAN 也被处理。

由于这个原因,我不确定我是否尝试以更好的方式执行此操作,但我正在尝试按照此帖中建议的解决方案中的说明进行操作:http://social.msdn.microsoft.com/Forums/vstudio/en-US/d7149a9a-b366-4983-98ff-5bf8875f67ec/wmlbuttondblclk-capturing-global-doubleclick

  

当您拦截WM_LBUTTONDOWN时,请通过GetMessageTime保存其时间   或GetTickCount函数。当您收到下一条消息时,请进行比较   保存的当前时间。如果差异小于那个   GetDoubleClickTime的值,然后双击。

问题在于有时候没有抓住双击,我在某种程度上错误地进行了评估。

有人可以帮助我知道我做错了什么以及如何解决这个问题?

以下是相关代码:

Private Function LowLevelMouseProc(ByVal nCode As Integer,
                                   ByVal wParam As MouseMessages,
                                   ByRef lParam As NativeMethods.MSLLHOOKSTRUCT) As Integer

    Static LeftClickTime As Long = 0L

    If nCode = 0I Then

        Select Case wParam

            Case MouseMessages.WM_LBUTTONDOWN
                RaiseEvent MouseLeftDown(Me, lParam.pt)

            Case MouseMessages.WM_LBUTTONUP

                LeftClickTime = GetMessageTime() - LeftClickTime

                If LeftClickTime < GetDoubleClickTime() Then
                    LeftClickTime = 0
                    RaiseEvent MouseLeftDoubleClick(Me, lParam.pt)

                Else
                    RaiseEvent MouseLeftUp(Me, lParam.pt)

                End If

                Debug.WriteLine(LeftClickTime)

            Case Else
                Exit Select ' Do Nothing

        End Select

        Return 0

    ElseIf nCode < 0I Then

        ' Initialize unmanged memory to hold the 'MSLLHOOKSTRUCT' structure.
        Dim pnt As IntPtr = Marshal.AllocHGlobal(Marshal.SizeOf(lParam))

        Try ' MSDN Documentation: http://msdn.microsoft.com/en-us/library/vstudio/4ca6d5z7%28v=vs.100%29.aspx

            ' Copy the struct to unmanaged memory.
            Marshal.StructureToPtr(lParam, pnt, False)

            ' Return 
            Return NativeMethods.CallNextHookEx(MouseHook, nCode, wParam, pnt)

        Finally
            ' Free the unmanaged memory.
            Marshal.FreeHGlobal(pnt)
        End Try

    Else ' nCode > 0

        Return -1I

    End If

End Function

<DllImport("user32.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Auto)>
Private Shared Function GetMessageTime() As Long
End Function

<DllImport("user32.dll", CallingConvention:=CallingConvention.StdCall, CharSet:=CharSet.Auto)>
Private Shared Function GetDoubleClickTime() As Long
End Function

然后如果首先运行钩子后我单击(LeftDown + LeftUp)然后双击(LeftDown + LeftUp + LeftDown + LeftUp),双击不会被解释为双击而是它会激活MouseLeftUp事件三次,但另一方面如果在运行Hook之后我首先执行一个DoubleClick,它会被正确检测到MouseLeftDoubleClick事件被触发。

PS:如果有人知道更好的解决方案来处理我真正感兴趣的应用程序中的WM_LBUTTONDBLCLK

1 个答案:

答案 0 :(得分:1)

最后,我找到了正确的检查:

Case MouseMessages.WM_LBUTTONUP

If LeftClickTime <> 0 Then
    LeftClickTime = (Environment.TickCount() - LeftClickTime)
End If

If (LeftClickTime <> 0) AndAlso (LeftClickTime < GetDoubleClickTime()) Then
    LeftClickTime = 0
    RaiseEvent MouseLeftDoubleClick(Me, lParam.pt)

Else
    LeftClickTime = Environment.TickCount()
    RaiseEvent MouseLeftUp(Me, lParam.pt)

End If

这样,我在验证双击时没有任何问题,至少在我测试过的情况下,我在问题结尾处描述的问题消失了。