Jump to content

(callback) Low Level Mouse Hook


_Kurt
 Share

Recommended Posts

Hi guys,

I'm not sure if someone else hasn't posted something like this, I didn't manage to find one through the search engine. I personally liked how it retrieves the mouse wheel state.

; ~~ Mouse Hook ~~
;For more info, Visit: http://msdn.microsoft.com/en-us/library/ms644986(VS.85).aspx

;Include GUI Consts
#include <GUIConstants.au3> ;for $GUI_EVENT_CLOSE
#Include <WinAPI.au3> ;for HIWORD

;These constants found in the helpfile under Windows Message Codes
Global Const $WM_MOUSEMOVE = 0x0200 ;mouse move
Global Const $WM_MOUSEWHEEL = 0x020A ;wheel up/down
Global Const $WM_LBUTTONDBLCLK = 0x0203 ;left button
Global Const $WM_LBUTTONDOWN = 0x0201
Global Const $WM_LBUTTONUP = 0x0202
Global Const $WM_RBUTTONDBLCLK = 0x0206 ;right button
Global Const $WM_RBUTTONDOWN = 0x0204
Global Const $WM_RBUTTONUP = 0x0205
Global Const $WM_MBUTTONDBLCLK = 0x0209 ;wheel clicks
Global Const $WM_MBUTTONDOWN = 0x0207
Global Const $WM_MBUTTONUP = 0x0208 

;Consts/structs from msdn
Global Const $MSLLHOOKSTRUCT = $tagPOINT & ";dword mouseData;dword flags;dword time;ulong_ptr dwExtraInfo"
;~ Global Const $WH_MOUSE_LL = 14           ;already declared
;~ Global Const $tagPOINT = "int X;int Y"   ;already declared

;Create GUI
$GUI = GUICreate("Mouse Hook", 178, 158, @DesktopWidth-178, 0) ;Top-Left corner
$_Event = GUICtrlCreateLabel("Event: ", 8, 8, 158, 17)
$_XYpos = GUICtrlCreateLabel("X=     Y=", 8, 32, 157, 17)
$_MData = GUICtrlCreateLabel("Mouse Data: ", 8, 56, 165, 17)
$_Flags = GUICtrlCreateLabel("Flags: ", 8, 80, 168, 17)
$_Timestamp = GUICtrlCreateLabel("Timestamp: ", 8, 104, 162, 17)
$_Extra = GUICtrlCreateLabel("Extra Info: ", 8, 128, 167, 17)
GUISetState()
WinSetOnTop($GUI, "", 1) ;make GUI stay on top of other windows

;Register callback
$hKey_Proc = DllCallbackRegister("_Mouse_Proc", "int", "int;ptr;ptr")
$hM_Module = DllCall("kernel32.dll", "hwnd", "GetModuleHandle", "ptr", 0)
$hM_Hook = DllCall("user32.dll", "hwnd", "SetWindowsHookEx", "int", $WH_MOUSE_LL, "ptr", DllCallbackGetPtr($hKey_Proc), "hwnd", $hM_Module[0], "dword", 0)


While 1
    If $GUI_EVENT_CLOSE = GUIGetMsg() Then Exit ;idle until exit is pressed
WEnd

Func _Mouse_Proc($nCode, $wParam, $lParam) ;function called for mouse events..
    ;define local vars
    Local $info, $ptx, $pty, $mouseData, $flags, $time, $dwExtraInfo
    Local $xevent = "Unknown", $xmouseData = ""
    
    If $nCode < 0 Then ;recommended, see http://msdn.microsoft.com/en-us/library/ms644986(VS.85).aspx
        $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
                "int", $nCode, "ptr", $wParam, "ptr", $lParam) ;recommended
        Return $ret[0]
    EndIf
    
    $info = DllStructCreate($MSLLHOOKSTRUCT, $lParam) ;used to get all data in the struct ($lParam is the ptr)
    $ptx = DllStructGetData($info, 1) ;see notes below..
    $pty = DllStructGetData($info, 2)
    $mouseData = DllStructGetData($info, 3)
    $flags = DllStructGetData($info, 4)
    $time = DllStructGetData($info, 5)
    $dwExtraInfo = DllStructGetData($info, 6)
    ; $ptx = Mouse x position
    ; $pty = Mouse y position
    ; $mouseData = can specify click states, and wheel directions
    ; $flags = Specifies the event-injected flag
    ; $time = Specifies the time stamp for this message
    ; $dwExtraInfo = Specifies extra information associated with the message. 

    ;Find which event happened
    Select
        Case $wParam = $WM_MOUSEMOVE
            $xevent = "Mouse Move"
        Case $wParam = $WM_MOUSEWHEEL
            $xevent = "Mouse Wheel"
            If _WinAPI_HiWord($mouseData) > 0 Then
                $xmouseData = "Wheel Forward"
            Else
                $xmouseData = "Wheel Backward"
            EndIf
        Case $wParam = $WM_LBUTTONDBLCLK
            $xevent = "Double Left Click"
        Case $wParam = $WM_LBUTTONDOWN
            $xevent = "Left Down"
        Case $wParam = $WM_LBUTTONUP
            $xevent = "Left Up"
        Case $wParam = $WM_RBUTTONDBLCLK
            $xevent = "Double Right Click"
        Case $wParam = $WM_RBUTTONDOWN
            $xevent = "Right Down"
        Case $wParam = $WM_RBUTTONUP
            $xevent = "Right Up"
        Case $wParam = $WM_MBUTTONDBLCLK
            $xevent = "Double Wheel Click"
        Case $wParam = $WM_MBUTTONDOWN
            $xevent = "Wheel Down"
        Case $wParam = $WM_MBUTTONUP
            $xevent = "Wheel Up"
    EndSelect
    
    ; Set GUI control data..
    GUICtrlSetData($_Event, "Event: " & $xevent)
    GUICtrlSetData($_XYpos, "X=" & $ptx & "     Y=" & $pty)
    If $xmouseData <> "" Then
        GUICtrlSetData($_MData, "Mouse Data: " & $xmouseData)
    Else
        GUICtrlSetData($_MData, "Mouse Data: " & $mouseData)
    EndIf
    GUICtrlSetData($_Flags, "Flags: " & $flags)
    GUICtrlSetData($_Timestamp, "Timestamp: " & $time)
    GUICtrlSetData($_Extra, "Extra Info: " & $dwExtraInfo)
    
    ;This is recommended instead of Return 0
    $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
            "int", $nCode, "ptr", $wParam, "ptr", $lParam)
    Return $ret[0]
EndFunc   ;==>_Mouse_Proc

Func OnAutoItExit()
    DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hM_Hook[0])
    $hM_Hook[0] = 0
    DllCallbackFree($hKey_Proc)
    $hKey_Proc = 0
EndFunc   ;==>OnAutoItExit

Resource: http://msdn.microsoft.com/en-us/library/ms644986(VS.85).aspx

Kurt

Awaiting Diablo III..

Link to comment
Share on other sites

Thanks, and sorry about the limited amount of comments.

I still am not really sure how $dwExtraInfo can be used, there is no useful comments from msdn.

Also, I've noticed that I don't ever receive the $WM_LBUTTONDBLCLK / $WM_RBUTTONDBLCLK / $WM_MBUTTONDBLCLK events.

Kurt

Awaiting Diablo III..

Link to comment
Share on other sites

I think _MouseSetOnEvent UDF uses this callback.

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

  • 4 weeks later...

here's some contribution from my side for x-button on your mouse:

add this in the top of the script:

Global Const $WM_XBUTTONDOWN = 0x020B ;x-button down
Global Const $WM_XBUTTONUP = 0x020CoÝ÷ Ù©Ý­êeiǢ릺~éÜÂ+a¶¬jëh×6Func _Mouse_Proc($nCode, $wParam, $lParam) ;function called for mouse events..
    ;define local vars
    Local $info, $ptx, $pty, $mouseData, $flags, $time, $dwExtraInfo
    Local $xevent = "Unknown", $xmouseData = ""
   
    If $nCode < 0 Then ;recommended, see http://msdn.microsoft.com/en-us/library/ms644986(VS.85).aspx
        $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
                "int", $nCode, "ptr", $wParam, "ptr", $lParam) ;recommended
        Return $ret[0]
    EndIf
   
    $info = DllStructCreate($MSLLHOOKSTRUCT, $lParam) ;used to get all data in the struct ($lParam is the ptr)
    $ptx = DllStructGetData($info, 1) ;see notes below..
    $pty = DllStructGetData($info, 2)
    $mouseData = DllStructGetData($info, 3)
    $flags = DllStructGetData($info, 4)
    $time = DllStructGetData($info, 5)
    $dwExtraInfo = DllStructGetData($info, 6)
    ; $ptx = Mouse x position
    ; $pty = Mouse y position
    ; $mouseData = can specify click states, and wheel directions
    ; $flags = Specifies the event-injected flag
    ; $time = Specifies the time stamp for this message
    ; $dwExtraInfo = Specifies extra information associated with the message.

    ;Find which event happened
    Select
        Case $wParam = $WM_MOUSEMOVE
            $xevent = "Mouse Move"
        Case $wParam = $WM_MOUSEWHEEL
            $xevent = "Mouse Wheel"
            If _WinAPI_HiWord($mouseData) > 0 Then
                $xmouseData = "Wheel Forward"
            Else
                $xmouseData = "Wheel Backward"
            EndIf
        case $wParam = $WM_XBUTTONDOWN
            $xevent = "x-button down"
            If _WinAPI_HiWord($mouseData) = 1 Then
                $xmouseData = "Forward"
            Else
                $xmouseData = "Backward"
            EndIf
        case $wParam = $WM_XBUTTONUP
            $xevent = "x-button up"
            If _WinAPI_HiWord($mouseData) = 1 Then
                $xmouseData = "Forward"
            Else
                $xmouseData = "Backward"
            EndIf
        Case $wParam = $WM_LBUTTONDBLCLK
            $xevent = "Double Left Click"
        Case $wParam = $WM_LBUTTONDOWN
            $xevent = "Left Down"
        Case $wParam = $WM_LBUTTONUP
            $xevent = "Left Up"
        Case $wParam = $WM_RBUTTONDBLCLK
            $xevent = "Double Right Click"
        Case $wParam = $WM_RBUTTONDOWN
            $xevent = "Right Down"
        Case $wParam = $WM_RBUTTONUP
            $xevent = "Right Up"
        Case $wParam = $WM_MBUTTONDBLCLK
            $xevent = "Double Wheel Click"
        Case $wParam = $WM_MBUTTONDOWN
            $xevent = "Wheel Down"
        Case $wParam = $WM_MBUTTONUP
            $xevent = "Wheel Up"
    EndSelect
   
    ; Set GUI control data..
    GUICtrlSetData($_Event, "Event: " & $xevent)
    GUICtrlSetData($_XYpos, "X=" & $ptx & "     Y=" & $pty)
    If $xmouseData <> "" Then
        GUICtrlSetData($_MData, "Mouse Data: " & $xmouseData)
    Else
        GUICtrlSetData($_MData, "Mouse Data: " & $mouseData)
    EndIf
    GUICtrlSetData($_Flags, "Flags: " & $flags)
    GUICtrlSetData($_Timestamp, "Timestamp: " & $time)
    GUICtrlSetData($_Extra, "Extra Info: " & $dwExtraInfo)
   
    ;This is recommended instead of Return 0
    $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
            "int", $nCode, "ptr", $wParam, "ptr", $lParam)
    Return $ret[0]
EndFunc   ;==>_Mouse_Proc
Edited by sandin
Link to comment
Share on other sites

  • 2 months later...

Hi, this is very good, BUT there is some error... On exiting script, when I push X button - Exit, script and mouse is blocked on half of second...

Why?

[quote name='dbzfanatic' post='609696' date='Nov 26 2008, 08:46 AM']This is a help forum not a "write this for me" forum.[/quote](Sorry for bad English) :)

Link to comment
Share on other sites

Aha, and is there a way to been fixed?

(I know for hook.dll, but I want to know is it possible to do it without any external dll's...)

Edited by n3nE

[quote name='dbzfanatic' post='609696' date='Nov 26 2008, 08:46 AM']This is a help forum not a "write this for me" forum.[/quote](Sorry for bad English) :)

Link to comment
Share on other sites

Hi guys,

I'm not sure if someone else hasn't posted something like this, I didn't manage to find one through the search engine. I personally liked how it retrieves the mouse wheel state.

; ~~ Mouse Hook ~~
;For more info, Visit: http://msdn.microsoft.com/en-us/library/ms644986(VS.85).aspx

;Include GUI Consts
#include <GUIConstants.au3> ;for $GUI_EVENT_CLOSE
#Include <WinAPI.au3> ;for HIWORD

;These constants found in the helpfile under Windows Message Codes
Global Const $WM_MOUSEMOVE = 0x0200 ;mouse move
Global Const $WM_MOUSEWHEEL = 0x020A ;wheel up/down
Global Const $WM_LBUTTONDBLCLK = 0x0203 ;left button
Global Const $WM_LBUTTONDOWN = 0x0201
Global Const $WM_LBUTTONUP = 0x0202
Global Const $WM_RBUTTONDBLCLK = 0x0206 ;right button
Global Const $WM_RBUTTONDOWN = 0x0204
Global Const $WM_RBUTTONUP = 0x0205
Global Const $WM_MBUTTONDBLCLK = 0x0209 ;wheel clicks
Global Const $WM_MBUTTONDOWN = 0x0207
Global Const $WM_MBUTTONUP = 0x0208 

;Consts/structs from msdn
Global Const $MSLLHOOKSTRUCT = $tagPOINT & ";dword mouseData;dword flags;dword time;ulong_ptr dwExtraInfo"
;~ Global Const $WH_MOUSE_LL = 14           ;already declared
;~ Global Const $tagPOINT = "int X;int Y"   ;already declared

;Create GUI
$GUI = GUICreate("Mouse Hook", 178, 158, @DesktopWidth-178, 0) ;Top-Left corner
$_Event = GUICtrlCreateLabel("Event: ", 8, 8, 158, 17)
$_XYpos = GUICtrlCreateLabel("X=     Y=", 8, 32, 157, 17)
$_MData = GUICtrlCreateLabel("Mouse Data: ", 8, 56, 165, 17)
$_Flags = GUICtrlCreateLabel("Flags: ", 8, 80, 168, 17)
$_Timestamp = GUICtrlCreateLabel("Timestamp: ", 8, 104, 162, 17)
$_Extra = GUICtrlCreateLabel("Extra Info: ", 8, 128, 167, 17)
GUISetState()
WinSetOnTop($GUI, "", 1) ;make GUI stay on top of other windows

;Register callback
$hKey_Proc = DllCallbackRegister("_Mouse_Proc", "int", "int;ptr;ptr")
$hM_Module = DllCall("kernel32.dll", "hwnd", "GetModuleHandle", "ptr", 0)
$hM_Hook = DllCall("user32.dll", "hwnd", "SetWindowsHookEx", "int", $WH_MOUSE_LL, "ptr", DllCallbackGetPtr($hKey_Proc), "hwnd", $hM_Module[0], "dword", 0)


While 1
    If $GUI_EVENT_CLOSE = GUIGetMsg() Then Exit ;idle until exit is pressed
WEnd

Func _Mouse_Proc($nCode, $wParam, $lParam) ;function called for mouse events..
    ;define local vars
    Local $info, $ptx, $pty, $mouseData, $flags, $time, $dwExtraInfo
    Local $xevent = "Unknown", $xmouseData = ""
    
    If $nCode < 0 Then ;recommended, see http://msdn.microsoft.com/en-us/library/ms644986(VS.85).aspx
        $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
                "int", $nCode, "ptr", $wParam, "ptr", $lParam) ;recommended
        Return $ret[0]
    EndIf
    
    $info = DllStructCreate($MSLLHOOKSTRUCT, $lParam) ;used to get all data in the struct ($lParam is the ptr)
    $ptx = DllStructGetData($info, 1) ;see notes below..
    $pty = DllStructGetData($info, 2)
    $mouseData = DllStructGetData($info, 3)
    $flags = DllStructGetData($info, 4)
    $time = DllStructGetData($info, 5)
    $dwExtraInfo = DllStructGetData($info, 6)
    ; $ptx = Mouse x position
    ; $pty = Mouse y position
    ; $mouseData = can specify click states, and wheel directions
    ; $flags = Specifies the event-injected flag
    ; $time = Specifies the time stamp for this message
    ; $dwExtraInfo = Specifies extra information associated with the message. 

    ;Find which event happened
    Select
        Case $wParam = $WM_MOUSEMOVE
            $xevent = "Mouse Move"
        Case $wParam = $WM_MOUSEWHEEL
            $xevent = "Mouse Wheel"
            If _WinAPI_HiWord($mouseData) > 0 Then
                $xmouseData = "Wheel Forward"
            Else
                $xmouseData = "Wheel Backward"
            EndIf
        Case $wParam = $WM_LBUTTONDBLCLK
            $xevent = "Double Left Click"
        Case $wParam = $WM_LBUTTONDOWN
            $xevent = "Left Down"
        Case $wParam = $WM_LBUTTONUP
            $xevent = "Left Up"
        Case $wParam = $WM_RBUTTONDBLCLK
            $xevent = "Double Right Click"
        Case $wParam = $WM_RBUTTONDOWN
            $xevent = "Right Down"
        Case $wParam = $WM_RBUTTONUP
            $xevent = "Right Up"
        Case $wParam = $WM_MBUTTONDBLCLK
            $xevent = "Double Wheel Click"
        Case $wParam = $WM_MBUTTONDOWN
            $xevent = "Wheel Down"
        Case $wParam = $WM_MBUTTONUP
            $xevent = "Wheel Up"
    EndSelect
    
    ; Set GUI control data..
    GUICtrlSetData($_Event, "Event: " & $xevent)
    GUICtrlSetData($_XYpos, "X=" & $ptx & "     Y=" & $pty)
    If $xmouseData <> "" Then
        GUICtrlSetData($_MData, "Mouse Data: " & $xmouseData)
    Else
        GUICtrlSetData($_MData, "Mouse Data: " & $mouseData)
    EndIf
    GUICtrlSetData($_Flags, "Flags: " & $flags)
    GUICtrlSetData($_Timestamp, "Timestamp: " & $time)
    GUICtrlSetData($_Extra, "Extra Info: " & $dwExtraInfo)
    
    ;This is recommended instead of Return 0
    $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
            "int", $nCode, "ptr", $wParam, "ptr", $lParam)
    Return $ret[0]
EndFunc   ;==>_Mouse_Proc

Func OnAutoItExit()
    DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hM_Hook[0])
    $hM_Hook[0] = 0
    DllCallbackFree($hKey_Proc)
    $hKey_Proc = 0
EndFunc   ;==>OnAutoItExit

Resource: http://msdn.microsoft.com/en-us/library/ms644986(VS.85).aspx

Kurt

Your script is very good but when i run this script, this will slow the speed of pointer ?

73 108 111 118 101 65 117 116 111 105 116

Link to comment
Share on other sites

  • 2 months later...

What is the parameter for $wParam when e.g. hold down lmb and moving mouse around?

Mouse move is 0x200 and lmb down is 0x201...

Thanks,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

I was messing with the WM_SETCURSOR message, it also reports mouse events.

#include <WindowsConstants.au3>
;Global Const $WM_MOUSEMOVE = 0x200
Global Const $WM_LBUTTONDOWN = 0x201
;Global Const $WM_LBUTTONUP = 0x202
Global Const $WM_RBUTTONDOWN = 0x204
Global Const $WM_RBUTTONUP = 0x205
Global Const $WM_MBUTTONDOWN = 0x207
Global Const $WM_MBUTTONUP = 0x208

Global $cursor = 0
$Gui = GuiCreate("Test", 300, 200)
GUISetState(@SW_SHOW)
Sleep(2000)
GUIRegisterMsg($WM_SETCURSOR, 'WM_SETCURSOR')
$OldCur = DllCall("user32.dll", "int", "GetCursor")
$Cur = DllCall("user32.dll", "int", "LoadCursorFromFile", "str","C:\windows\cursors\hmove.cur")
While 1
    $Msg = GUIGetMsg()
    Sleep(10)
    If $Msg = -3 Then Exit; $GUI_EVENT_CLOSE
WEnd

Func WM_SETCURSOR($hWnd, $iMsg, $iWParam, $iLParam)
    $iLParamhigh = BitShift($iLParam, 16);HiWord
    $iLParamlow  = BitAnd($iLParam, 0x0000FFFF);LoWord
    If $hWnd = $Gui Then
        If $iLParamlow = 1 Then 
            tooltip("0x" & hex($iLParamhigh, 4))
            If $cursor = 0 Then
                beep(800,10)
                $cursor = 1
                DllCall("user32.dll", "int", "SetCursor", "int", $Cur[0])
            EndIf
        Else
            $cursor = 0
            DllCall("user32.dll", "int", "SetCursor", "int", $OldCur[0])
        EndIf
    Else
        $cursor = 0
        tooltip("")
    EndIf
    Return 0
EndFunc
Link to comment
Share on other sites

I'm just curious, how did these:

Global Const $WM_MOUSEMOVE = 0x200

Global Const $WM_LBUTTONUP = 0x202

find their way into WindowsConstants.au3, but not these:

Global Const $WM_LBUTTONDOWN = 0x201

Global Const $WM_RBUTTONDOWN = 0x204

Global Const $WM_RBUTTONUP = 0x205

Global Const $WM_MBUTTONDOWN = 0x207

Global Const $WM_MBUTTONUP = 0x208

???

I've noticed that one before

submit it to Trac

I see fascists...

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...