我的 MouseHook 阻止了其他应用程序的挂钩通知

My MouseHook is blocking the hook notifications of other applications

我已经实现了一个 LL 鼠标钩子,如果鼠标在指定区域移动,它会在鼠标接收到移动时进行捕获。

问题是当我的鼠标挂钩处于活动状态时,它会阻止其他应用程序的挂钩,其他应用程序试图捕获鼠标事件。 例如 FoldersPopup,它是一个小巧的免费应用程序,它在 windows 资源管理器标题栏上挂钩 中间 鼠标按钮以打开菜单,当我的挂钩是激活,那个程序的钩子不起作用。

我不知道这是否是我的挂钩或那些第 3 方挂钩的设计问题,但我认为是我的错,因为 MSDN 文档谈到了这种阻塞,而我当时并不理解所有这些值都应该 return 我在不同情况下的程序 return 正在计算一个值。

如果 class 实例被禁用(使用自定义 IsEnabled 属性),我 return 0

如果鼠标位置不在指定区域内(自定义WorkingArea属性),我return0

如果nCode参数是0,我return0

如果nCode参数大于0,我return-1

如果nCode参数小于0,我return下一个CallNextHookEx整数值。

我做错了什么?

Public Class MyMouseHook

    ' ( More code removed )
    Public Sub New()
    End Sub
    ' ( More code removed )

    ''' <summary>
    ''' Processes the mouse windows messages and raises it's corresponding events.
    ''' MSDN Documentation: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644986%28v=vs.85%29.aspx
    ''' </summary>
    ''' <param name="nCode">
    ''' A code the hook procedure uses to determine how to process the message. 
    ''' If nCode is less than zero, the hook procedure must pass the message to the CallNextHookEx function 
    ''' without further processing and should return the value returned by CallNextHookEx. 
    ''' </param>
    ''' <param name="wParam">The identifier of the mouse message.</param>
    ''' <param name="lParam"> A pointer to an <see cref="NativeMethods.MSLLHOOKSTRUCT"/> structure.</param>
    ''' <returns>
    ''' If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx.
    ''' If nCode is greater than or equal to zero, and the hook procedure did not process the message,
    ''' it is highly recommended that you call CallNextHookEx and return the value it returns;
    ''' otherwise, other applications that have installed WH_MOUSE_LL hooks will not receive hook notifications
    ''' and may behave incorrectly as a result.
    ''' If the hook procedure processed the message,
    ''' it may return a nonzero value to prevent the system from passing the 
    ''' message to the rest of the hook chain or the target window procedure.
    ''' </returns>
    Private Function LowLevelMouseProc(ByVal nCode As Integer,
                                       ByVal wParam As NativeMethods.WindowsMessages,
                                       ByVal lParam As IntPtr) As Integer

        ' This class contains an 'IsEnabled' property to 
        ' disable the mouse hook instance.
        ' If 'IsEnabled' is disabled then I return, 
        ' to avoid the code processing below. 
        If Not Me.IsEnabled Then
            Return 0
        End If

        If nCode = 0 Then

            ' The class contains a 'WorkingArea' property that 
            ' limits the hook to work only if the
            ' mouse coordinates are inside that working area.
            Dim x As Integer
            Dim y As Integer

            Dim mouseStruct As NativeMethods.MsllHookStruct = 
                CType(Marshal.PtrToStructure(lParam, mouseStruct.GetType()), 
                      NativeMethods.MsllHookStruct)

            ' ( More code removed )

            ' If mouse coordinates are not inside the 'WorkingArea' then return, 
            ' to avoid the code processing below.
            If x <= Me.WorkingArea.Width AndAlso
               y < Me.WorkingArea.Height AndAlso
               mouseStruct.Pt.X > Me.WorkingArea.Width Then

                Return 0

            ' ( More code removed )

            End If

            Select Case wParam

                Case NativeMethods.WindowsMessages.WM_MOUSEMOVE
                    RaiseEvent MouseMove(Me, New Point(x, y))

                Case Else
                    ' Do Nothing
                    Exit Select

            End Select

            Return 0

        ElseIf nCode < 0 Then
            Return CInt(NativeMethods.CallNextHookEx(MouseHook, 
                                                     nCode, 
                                                     New IntPtr(wParam), 
                                                     lParam))

        Else ' nCode > 0
            Return -1

        End If

    End Function

End Class

这里是完整的 mousehook 源代码,如果你想测试的话,它的普遍用法很容易测试这个问题的进一步答案,源代码只需要 1 copy/paste 步骤。

http://pastebin.com/gxfiqb0i

引用 MSDN 文档:

If nCode is less than zero, the hook procedure must return the value returned by CallNextHookEx.

If nCode is greater than or equal to zero, and the hook procedure did not process the message, it is highly recommended that you call CallNextHookEx and return the value it returns; otherwise, other applications that have installed WH_MOUSE_LL hooks will not receive hook notifications and may behave incorrectly as a result. If the hook procedure processed the message, it may return a nonzero value to prevent the system from passing the message to the rest of the hook chain or the target window procedure.

不调用 CallNextHookEx 意味着其他应用程序不会收到该事件,因此您的观察是有道理的。如果您有意结束挂钩链,则不应调用 CallNextHookEx