﻿Imports System.Runtime.InteropServices
Public Class MouseHook
    ''Constants
    Private Const HC_ACTION As Integer = 0
    Private Const WH_MOUSE_LL As Integer = 14
    Private Const WM_MOUSEMOVE As Integer = &H200
    Private Const WM_LBUTTONDOWN As Integer = &H201
    Private Const WM_LBUTTONUP As Integer = &H202
    Private Const WM_LBUTTONDBLCLK As Integer = &H203
    Private Const WM_RBUTTONDOWN As Integer = &H204
    Private Const WM_RBUTTONUP As Integer = &H205
    Private Const WM_RBUTTONDBLCLK As Integer = &H206
    Private Const WM_MBUTTONDOWN As Integer = &H207
    Private Const WM_MBUTTONUP As Integer = &H208
    Private Const WM_MBUTTONDBLCLK As Integer = &H209
    Private Const WM_MOUSEWHEEL As Integer = &H20A

    ''Mouse Structures
    Public Structure POINT
        Public x As Integer
        Public y As Integer
    End Structure

    Public Structure MSLLHOOKSTRUCT
        Public pt As POINT
        Public mouseData As Integer
        Private flags As Integer
        Private time As Integer
        Private dwExtraInfo As Integer
    End Structure

    ''API Functions
    Private Declare Function SetWindowsHookEx Lib "user32" Alias "SetWindowsHookExA" (ByVal idHook As Integer, ByVal lpfn As MouseProcDelegate, ByVal hmod As Integer, ByVal dwThreadId As Integer) As Integer
    Private Declare Function CallNextHookEx Lib "user32" (ByVal hHook As Integer, ByVal nCode As Integer, ByVal wParam As Integer, ByVal lParam As MSLLHOOKSTRUCT) As Integer
    Private Declare Function UnhookWindowsHookEx Lib "user32" (ByVal hHook As Integer) As Integer

    ''Our Mouse Delegate
    Private Delegate Function MouseProcDelegate(ByVal nCode As Integer, ByVal wParam As Integer, ByRef lParam As MSLLHOOKSTRUCT) As Integer
    ''The Mouse events
    Public Shared Event MouseMove(ByVal ptLocat As POINT)
    Public Shared Event MouseEvent(ByVal mEvent As Integer)
    Public Shared Event WheelEvent(ByVal wEvent As MSLLHOOKSTRUCT)

    ''The identifyer for our MouseHook
    Private Shared MouseHook As Integer
    ''MouseHookDelegate
    Private Shared MouseHookDelegate As MouseProcDelegate

    Public Sub New()
        ''Installs a Low Level Mouse Hook
        MouseHookDelegate = New MouseProcDelegate(AddressOf MouseProc)
        MouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookDelegate, Marshal.GetHINSTANCE(System.Reflection.Assembly.GetExecutingAssembly.GetModules()(0)).ToInt32, 0)

    End Sub


    Private Shared Function MouseProc(ByVal nCode As Integer, ByVal wParam As Integer, ByRef lParam As MSLLHOOKSTRUCT) As Integer
        ''If it is a Mouse event
        If (nCode = HC_ACTION) Then
            If wParam = WM_MOUSEMOVE Then
                ''If it is the mouse moving
                RaiseEvent MouseMove(lParam.pt)
            ElseIf wParam = WM_LBUTTONDOWN Or wParam = WM_LBUTTONUP Or wParam = WM_LBUTTONDBLCLK Or wParam = WM_RBUTTONDOWN Or wParam = WM_RBUTTONUP Or wParam = WM_RBUTTONDBLCLK Or wParam = WM_MBUTTONDOWN Or wParam = WM_MBUTTONUP Or wParam = WM_MBUTTONDBLCLK Then
                ''If it is a different mouse event
                RaiseEvent MouseEvent(wParam)
            ElseIf wParam = WM_MOUSEWHEEL Then
                RaiseEvent WheelEvent(lParam)
            End If
        End If
        ''Next
        Return CallNextHookEx(MouseHook, nCode, wParam, lParam)
    End Function

    Protected Overrides Sub Finalize()
        UnhookWindowsHookEx(MouseHook)
        MyBase.Finalize()
    End Sub
End Class