Link to home
Start Free TrialLog in
Avatar of romieb69
romieb69Flag for United States of America

asked on

Stop Click Event Within Low Level Mouse Hook - VB.NET

Good afternoon folks.

I'm at the last stage of a piece I'm adding to a project of mine and running into a slight snag. I have a low level mouse hook being implemented to intercept the left mouse button down event taking place on another form. Everything works great except for one thing: The click event depresses the button that I'm monitoring. I can't allow that button to actually be depressed.

I was thinking that within my hook I could simply return 0 at the point where I catch the mouse down event and that would be it... apparently it's not that simple or I'm overlooking something stupid =)  

I've attached the full working class that hooks the mouse and sets my boolean property. Where you see the line Return 0 ... my hope was that the event would be sent to garbage collection and not actually depress the button they clicked.

Many thanks!!!
Public Class clsMouseHook
    Private Structure MSLLHOOKSTRUCT
        Public pt As Point
        Public mouseData As Int32
        Public flags As Int32
        Public time As Int32
        Public extra As IntPtr
    End Structure
    Public hndl As Integer
    Public p_btnClicked As Boolean = False
    Private _mouseHook As IntPtr
    Private Const WH_MOUSE_LL As Int32 = 14
    Private Delegate Function MouseHookDelegate(ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32 '<MarshalAs(UnmanagedType.FunctionPtr)>
    Private _mouseProc As MouseHookDelegate
    Private Declare Function SetWindowsHookExW Lib "user32.dll" (ByVal idHook As Int32, ByVal HookProc As MouseHookDelegate, ByVal hInstance As IntPtr, ByVal wParam As Int32) As IntPtr
    Private Declare Function UnhookWindowsHookEx Lib "user32.dll" (ByVal hook As IntPtr) As Boolean
    Private Declare Function CallNextHookEx Lib "user32.dll" (ByVal idHook As Int32, ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32
    Private Declare Function GetCurrentThreadId Lib "kernel32.dll" () As Integer
    Private Declare Function GetModuleHandleW Lib "kernel32.dll" (ByVal fakezero As IntPtr) As IntPtr
    Public Declare Function WindowFromPoint Lib "user32" (ByVal pt As PointAPI) As IntPtr
    Public Structure PointAPI
        Public X As Integer
        Public Y As Integer
        Public Sub New(ByVal pt As Point)
            X = pt.X
            Y = pt.Y
        End Sub
    End Structure


    Public Function HookMouse(ByVal btnHndl As Integer) As Boolean
        If _mouseHook = IntPtr.Zero Then
            _mouseProc = New MouseHookDelegate(AddressOf MouseHookProc)
            _mouseHook = SetWindowsHookExW(WH_MOUSE_LL, _mouseProc, GetModuleHandleW(IntPtr.Zero), 0)
        End If
        hndl = btnHndl 'stores the button handle that was passed in during the hook process
        Return _mouseHook <> IntPtr.Zero
    End Function

    Public Sub UnHookMouse()
        If _mouseHook = IntPtr.Zero Then Return
        UnhookWindowsHookEx(_mouseHook)
        hndl = 0
        _mouseHook = IntPtr.Zero
    End Sub

    Private Function MouseHookProc(ByVal nCode As Int32, ByVal wParam As IntPtr, ByRef lParam As MSLLHOOKSTRUCT) As Int32
        Dim clkHndl As IntPtr
        If wParam.ToInt32 = 513 Then 'interrupt the left mouse button event here with 513
            If hndl <> 0 Then 'check to make sure we have a button handle
                'need to now determine if where the left click took place is on the button's location
                'clkHndl = sc.GetHandleFromLocation(lParam.pt.Y, lParam.pt.X)
                clkHndl = WindowFromPoint(New PointAPI(Cursor.Position))
                ' ... now use clkHndl to find out if it matches the stored button windows handle
                If clkHndl = hndl Then
                    BtnClicked = True
                    Return 0
                End If
            End If
        End If
        Return CallNextHookEx(WH_MOUSE_LL, nCode, wParam, lParam)
    End Function
    Public Property BtnClicked() As Boolean
        Get
            Return p_btnClicked
        End Get
        Set(ByVal value As Boolean)
            p_btnClicked = value
        End Set
    End Property

End Class

Open in new window

Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Pretty sure you need to return 1 instead of 0 (one instead of zero).

Change:

                    Return 0

To:

                    Return 1 ' <-- Suppress mouse event
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of romieb69

ASKER

LOL... I hate it when that happens  =)  Thanks IM!