MouseHook中MSLLHOOKSTRUCT.mouseData处理MouseWheel时值始终相同的问题
鼠标钩子无法区分滚轮前后方向问题
我已在网上竭力搜索并尝试了所有能找到的解决方案,但仍未找到可行办法。我使用鼠标钩子已有很长时间,除了无法区分鼠标滚轮向前/向后的消息外,其他功能均正常。我见过MSLLHOOKSTRUCT结构的mouseData成员被声明为Integer和UInteger,但无论采用哪种声明方式,我都无法获取WM_MOUSEWHEEL消息的HIWORD来区分滚轮方向,因为向前和向后滚动时该值始终相同。
测试输出
滚轮向前:
mouseData: 23074474
HIWORD: 352
滚轮向后:
mouseData: 23074474
HIWORD: 352
代码
<Extension> Public Function HIWORD(value As Integer) As Integer Return BitConverter.ToInt16(BitConverter.GetBytes(value), 2) End Function Private Shared MouseHookProcedure As HookProcHandler Private Shared PreviousCallback As Object() Private Shared ProcPtrSet As Boolean Private Shared HookHandle As IntPtr Public Shared Function Start() As Boolean If HookHandle <> IntPtr.Zero Then Return True If Not ProcPtrSet Then ProcPtrSet = True MouseHookProcedure = New HookProcHandler(AddressOf HookProc) End If Using p As Process = Process.GetCurrentProcess() Using m As ProcessModule = p.MainModule SetWindowsHookEx(HOOKTYPE.WH_MOUSE, MouseHookProcedure, Pinvoke.Kernel32.Functions.GetModuleHandle(m.ModuleName), Pinvoke.Kernel32.Functions.GetCurrentThreadId) End Using End Using If HookHandle = 0 Then Return False Else Return True End Function Public Shared Function [Stop]() As Boolean Return UnhookWindowsHookEx(HookHandle) End Function Private Shared Function HookProc(nCode As Integer, wParam As IntPtr, lParam As IntPtr) As Integer Dim MSLLHS As MSLLHOOKSTRUCT = Marshal.PtrToStructure(lParam, GetType(MSLLHOOKSTRUCT)) If nCode < 0 Then Return CallNextHookEx(HookHandle, nCode, wParam, lParam) Else ' Catch duplicate messages caused by the default behavior of the MouseProc function. Dim Msg As MouseMessages = CType(wParam, MouseMessages) If PreviousCallback IsNot Nothing Then If CType(PreviousCallback(0), MouseMessages) = Msg AndAlso CompairMSLLHOOKSRUCT(PreviousCallback(1), MSLLHS) AndAlso CType(PreviousCallback(2), Date) = Now Then GoTo NextCallback End If End If ' Raise Event Select Case Msg Case MouseMessages.MouseWheel Msg = If(CType(MSLLHS.mouseData, Integer).HIWORD > 0, MouseMessages.MouseWheelForward, MouseMessages.MouseWheelBack) RaiseEvent Message(Msg, MSLLHS) Case Else RaiseEvent Message(Msg, MSLLHS) End Select PreviousCallback = New Object(2) {CType(wParam, MouseMessages), MSLLHS, Now} NextCallback: Try Return CallNextHookEx(HookHandle, nCode, wParam, lParam) Catch ex As Exception Return [Stop]() End Try End If End Function Private Shared Function CompairMSLLHOOKSRUCT(left As MSLLHOOKSTRUCT, right As MSLLHOOKSTRUCT) As Boolean Return left.pt.X = right.pt.X AndAlso left.pt.Y = right.pt.Y AndAlso left.mouseData = right.mouseData AndAlso left.flags = right.flags AndAlso left.time = right.time AndAlso left.dwExtraInfo = right.dwExtraInfo End Function
Pinvoke定义
Public Delegate Function HookProcHandler(nCode As System.Int32, wParam As System.IntPtr, lParam As System.IntPtr) As System.Int32 <DllImport(User32, CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)> Public Shared Function UnhookWindowsHookEx(idHook As System.IntPtr) As System.Boolean End Function <DllImport(User32, CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)> Public Shared Function SetWindowsHookEx(idHook As System.Int32, lpfn As HookProcHandler, hInstance As System.IntPtr, threadId As System.Int32) As System.IntPtr End Function <DllImport(User32, CharSet:=CharSet.Auto, CallingConvention:=CallingConvention.StdCall, SetLastError:=True)> Public Shared Function CallNextHookEx(hhk As System.IntPtr, nCode As System.Int32, wParam As System.IntPtr, lParam As System.IntPtr) As System.IntPtr End Function <DllImport(Kernel32, CharSet:=CharSet.Auto, SetLastError:=True)> Public Shared Function GetModuleHandle(lpModuleName As System.String) As System.IntPtr End Function <StructLayout(LayoutKind.Sequential)> Public Structure MSLLHOOKSTRUCT Public pt As POINT Public mouseData As System.UInt32 Public flags As System.UInt32 Public time As System.UInt32 Public dwExtraInfo As System.IntPtr End Structure <StructLayout(LayoutKind.Sequential)> Public Structure POINT Public X As System.Int32 Public Y As System.Int32 Public Sub New(ByVal X As System.Int32, ByVal Y As System.Int32) Me.X = X Me.Y = Y End Sub End Structure Public Enum MouseMessages As System.UInt32 MouseWheel = WindowsMessages.WM_MOUSEWHEEL ' &H20E ' Etc... End Enum
补充说明
以下并非原问题的延续或补充问题,而是对Remy Lebeau提供的解决方案的补充说明。
供有需要的用户参考,MOUSEHOOKSTRUCTEX的定义如下:
<StructLayout(LayoutKind.Sequential)> Public Structure MOUSEHOOKSTRUCTEX Public mouseHookStruct As MOUSEHOOKSTRUCT Public mouseData As System.Int32 End Structure
非常感谢大家的帮助!
内容的提问来源于stack exchange,提问作者John89
相关产品推荐
相关产品推荐

