Jump to content

Modify Side mouse button behaviour


Inpho
 Share

Recommended Posts

Hi All,

A co-worker complained that the side keys on his mouse (back and forward) were getting in the way. This script allows you to disable/re-purpose those buttons. 

Have only tested with a Delux M618 mouse.
Haven't tested under Windows 10.

This is the standalone version of the script so it will look ugly. The (cleaner) version we're using has a bunch of server calls and auto-update checks.

Please report any problems here; even if you fix them yourself. Learning curve etc.

 

#include <Misc.au3>
#include <WinAPI.au3>
#include <GuiComboBoxEx.au3>
#include <ComboConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>

Global $gLastHotKeyPressed = ""; Last Hot key pressed
Global $gLastHotKeyType = "" ; Last Hot key pressed type

Global Const $MSLLHOOKSTRUCT = $tagPOINT & ";dword mouseData;dword flags;dword time;ulong_ptr dwExtraInfo"
Global Const $MOUSETRAPEVENT_DUMMY = "_MouseTrapEvent_Dummy"

Global $currentEvent[2]
Global $currentDownEvent[2]

Global $lastEvent = ""

Global $iLBUTTONDOWN = 0
Global $iRBUTTONDOWN = 0
Global $iMBUTTONDOWN = 0
Global $iXBUTTONDOWNNumber = 0 ; 1 or 2 xtra buttons
Global $LRClickStatus = 0
Global $RLClickStatus = 0
Global $LRDrag = 0
Global $RLDrag = 0
Global $LMDrag = 0
Global $RMDrag = 0
Global $doubleClickTime = 400

Global $gLastMouseEventPressed = "" ; Added for HotKeySetEx  UDF
;Global $gLastHotKeyPressed = ""; Last Hot key pressed Added for HotKeySetEx  UDF
;Global $gLastHotKeyType = "" ; Last Hot key pressed type Added for HotKeySetEx  UDF

; Mouse On event variables
Global $a__MSOE_Events[1][1]
Global $a__MSOE_DblClk_Data = __MouseTrapEvent_GetDoubleClickData()
$doubleClickTime = $a__MSOE_DblClk_Data[0] + 50

Global $hKey_Proc
Global $hM_Module
Global $hM_Hook

If _Singleton("MouseKeyModifier.exe", 1) = 0 Then
    MsgBox(0, "Warning", "Mouse Key Modifier is already running.")
    Exit
EndIf

TrayTip("MKM", "MouseKeyModifier is running. Click here for options", 30)

Global $sHotKeyBack = ""
Global $sHotKeyForward = ""

Opt("TrayMenuMode", 1)
Main()

Func Main()

    HotKeySetEx("{XClick12}", "_FuncDummy", 1)
    Local $tMsg
    Local Static $aArray = _MouseKeyModifierTrayCreate()

    Local Static $cTraySettings = $aArray[1]
    Local Static $cTrayBehaviour = $aArray[2]
    Local Static $cTrayBehaviourStandard = $aArray[3]
    Local Static $cTrayBehaviourCustom = $aArray[4]
    Local Static $cTrayBehaviourStartup = $aArray[5]
    Local Static $cTrayQuickDisable = $aArray[6]
    Local Static $cTrayExit = $aArray[7]

    Local Static $sCurrentBehaviour = IniRead(@ScriptDir & "\config.ini", "DefaultBehaviour", "Hotkey", "Standard")
    If $sCurrentBehaviour = "Standard" Then
        TrayItemSetState($cTrayBehaviourStandard, 1)
    ElseIf $sCurrentBehaviour = "Custom" Then
        TrayItemSetState($cTrayBehaviourCustom, 1)
        _HotKeysSet()
    ElseIf $sCurrentBehaviour = "Disable" Then
        TrayItemSetState($cTrayQuickDisable, 1)
        _HotKeysQuickDisable(True)
    EndIf

    While 1
        $tMsg = TrayGetMsg()
        Switch $tMsg
            Case $cTraySettings

                TraySetState(2)
                TrayItemSetState($cTraySettings, 4)
                _HotKeysUpdateSettingsGuiLoop($sCurrentBehaviour)
                TraySetState(1)

            Case $cTrayBehaviourStandard

                _HotKeysQuickDisable(False)
                TrayItemSetState($cTrayQuickDisable, 4)
                TrayItemSetState($cTrayBehaviourStandard, 1)
                TrayItemSetState($cTrayBehaviourCustom, 4)
                $sCurrentBehaviour = "Standard"

            Case $cTrayBehaviourCustom

                _HotKeysQuickDisable(False)
                TrayItemSetState($cTrayQuickDisable, 4)
                TrayItemSetState($cTrayBehaviourStandard, 4)
                TrayItemSetState($cTrayBehaviourCustom, 1)
                $sCurrentBehaviour = "Custom"
                _HotKeysSet()

            Case $cTrayQuickDisable

                If BitAND(TrayItemGetState($cTrayQuickDisable), 1) = 1 Then

                    _HotKeysQuickDisable(True)
                    TrayItemSetState($cTrayQuickDisable, 1)
                    TrayItemSetState($cTrayBehaviourStandard, 4)
                    TrayItemSetState($cTrayBehaviourCustom, 4)

                ElseIf BitAND(TrayItemGetState($cTrayQuickDisable), 4) = 4 Then

                    _HotKeysQuickDisable(False)
                    TrayItemSetState($cTrayQuickDisable, 4)
                    If $sCurrentBehaviour = "Standard" Then
                        TrayItemSetState($cTrayBehaviourStandard, 1)
                        TrayItemSetState($cTrayBehaviourCustom, 4)
                    ElseIf $sCurrentBehaviour = "Custom" Then
                        TrayItemSetState($cTrayBehaviourStandard, 4)
                        TrayItemSetState($cTrayBehaviourCustom, 1)
                        _HotKeysSet()
                    ElseIf $sCurrentBehaviour = "Disable" Then
                        $sCurrentBehaviour = "Standard"
                        TrayItemSetState($cTrayBehaviourStandard, 1)
                        TrayItemSetState($cTrayBehaviourCustom, 4)
                    EndIf
                EndIf

            Case $cTrayBehaviourStartup

                TraySetState(2)
                If BitAND(TrayItemGetState($cTrayBehaviourStandard), 1) = 1 Then
                    IniWrite(@ScriptDir & "\config.ini", "DefaultBehaviour", "Hotkey", "Standard")
                    MsgBox(0, "Success", "'Standard' set as default at startup.")
                ElseIf BitAND(TrayItemGetState($cTrayBehaviourCustom), 1) = 1 Then
                    IniWrite(@ScriptDir & "\config.ini", "DefaultBehaviour", "Hotkey", "Custom")
                    MsgBox(0, "Success", "'Custom' set as default at startup.")
                ElseIf BitAND(TrayItemGetState($cTrayQuickDisable), 1) = 1 Then
                    IniWrite(@ScriptDir & "\config.ini", "DefaultBehaviour", "Hotkey", "Disable")
                    MsgBox(0, "Success", "'Disabled' set as default at startup.")
                EndIf

                TraySetState(1)
                TrayItemSetState($cTrayBehaviourStartup, 4)

            Case $cTrayExit
                Exit
        EndSwitch
    WEnd

EndFunc   ;==>Main

Func _CheckDeselect($cFrom, $cTo)

    Local $i

    For $i = $cFrom To $cTo
        GUICtrlSetState($i, 4)
    Next

    Return (1)

EndFunc   ;==>_CheckDeselect

Func _CheckToString($cCheckWin, $cCheckCtrl, $cCheckAlt, $cCheckShift)

    Local $sReturn = ""
    Local $i

    If GUICtrlRead($cCheckWin) = 1 Then $sReturn &= "#"
    If GUICtrlRead($cCheckCtrl) = 1 Then $sReturn &= "^"
    If GUICtrlRead($cCheckAlt) = 1 Then $sReturn &= "!"
    If GUICtrlRead($cCheckShift) = 1 Then $sReturn &= "+"

    Return ($sReturn)

EndFunc   ;==>_CheckToString

Func _ComboDeselect($hWnd, $cControl)

    ControlCommand($hWnd, "", $cControl, "SetCurrentSelection", "-1")

    Return (1)

EndFunc   ;==>_ComboDeselect

Func _ControlDisable($cFrom, $cTo, $bDisable = True)

    Local $i

    For $i = $cFrom To $cTo
        If $bDisable = True Then
            GUICtrlSetState($i, 4 + 128)
        Else
            GUICtrlSetState($i, 4 + 64)
        EndIf
    Next

    Return (1)

EndFunc   ;==>_ControlDisable

Func _FuncDummy()

    Return (1)

EndFunc   ;==>_FuncDummy

Func _FuncHotKeyBack()

    Send($sHotKeyBack)

    Return (1)

EndFunc   ;==>_FuncHotKeyBack

Func _FuncHotKeyForward()

    Send($sHotKeyForward)

    Return (1)

EndFunc   ;==>_FuncHotKeyForward

Func _HotKeysAssign($sMouseButton, $sString)

    If $sMouseButton = "Back" Then
        HotKeySetEx("{XClick1}", "_FuncHotKeyBack", 1)
        HotKeySetEx("{XDClick1}", "_FuncHotKeyBack", 1)
    ElseIf $sMouseButton = "Forward" Then
        HotKeySetEx("{XClick2}", "_FuncHotKeyForward", 1)
        HotKeySetEx("{XDClick2}", "_FuncHotKeyForward", 1)
    EndIf

    Return (1)

EndFunc   ;==>_HotKeysAssign

Func _HotKeysUpdateSettingsGuiLoop($sCurrentBehaviour)

    Local Static $aArray = _MouseKeyModifierSettingsGuiCreate()

    Local Static $cGui = $aArray[1]
    Local Static $cComboButton = $aArray[2]
    Local Static $cCheckWin = $aArray[3]
    Local Static $cCheckCtrl = $aArray[4]
    Local Static $cCheckAlt = $aArray[5]
    Local Static $cCheckShift = $aArray[6]
    Local Static $cComboCharacter = $aArray[7]
    Local Static $cCheckDisable = $aArray[8]
    Local Static $cButtonSave = $aArray[9]
    Local Static $cButtonCancel = $aArray[10]

    GUICtrlSetState($cCheckWin, 4)
    GUICtrlSetState($cCheckCtrl, 4)
    GUICtrlSetState($cCheckAlt, 4)
    GUICtrlSetState($cCheckShift, 4)

    _ComboDeselect($cGui, $cComboButton)
    _ComboDeselect($cGui, $cComboCharacter)

    Local $sStringToSave = "", $sButtonToSave = ""
    Local $iIndex

    GUISetState(@SW_SHOW, $cGui)

    While 1
        $nMsg = GUIGetMsg()
        Switch $nMsg
            Case -3, $cButtonCancel

                GUISetState(@SW_HIDE, $cGui)
                Return

            Case $cComboButton

                ConsoleWrite(GUICtrlRead($cComboButton) & @CRLF)
                _ComboDeselect($cGui, $cComboCharacter)
                _HotKeysUpdateSettingsGuiControls(GUICtrlRead($cComboButton), $cCheckWin, $cCheckCtrl, $cCheckAlt, $cCheckShift, $cComboCharacter)

            Case $cCheckDisable

                ConsoleWrite(GUICtrlRead($cCheckDisable) & @CRLF)
                If GUICtrlRead($cCheckDisable) = 1 Then
                    _ControlDisable($cCheckWin, $cComboCharacter, True)
                    _ComboDeselect($cGui, $cComboCharacter)
                ElseIf GUICtrlRead($cCheckDisable) = 4 Then
                    _ControlDisable($cCheckWin, $cComboCharacter, False)
                EndIf

            Case $cButtonSave

                $sButtonToSave = GUICtrlRead($cComboButton)
                If $sButtonToSave = "" Then
                    MsgBox(0, "Error", "You must select a button to modify.", 0, $cGui)
                    ContinueLoop
                EndIf

                If GUICtrlRead($cCheckDisable) = 1 Then
                    _HotKeysSaveToFile($sButtonToSave, "{EMPTY}")
                Else
                    $sStringToSave = _CheckToString($cCheckWin, $cCheckCtrl, $cCheckAlt, $cCheckShift)
                    $iIndex = _GUICtrlComboBox_GetCurSel($cComboCharacter)
                    If $iIndex <> -1 Then $sStringToSave &= GUICtrlRead($cComboCharacter)
                    If $sStringToSave = "" Then $sStringToSave = "{EMPTY}"
                    _HotKeysSaveToFile($sButtonToSave, $sStringToSave)
                EndIf

                _CheckDeselect($cCheckWin, $cCheckShift)
                _CheckDeselect($cCheckDisable, $cCheckDisable)
                _ComboDeselect($cGui, $cComboButton)
                _ComboDeselect($cGui, $cComboCharacter)

                If $sCurrentBehaviour = "Custom" Then _HotKeysSet()

        EndSwitch
    WEnd

EndFunc   ;==>_HotKeysUpdateSettingsGuiLoop

Func _HotKeysUpdateSettingsGuiControls($sButton, $cCheckWin, $cCheckCtrl, $cCheckAlt, $cCheckShift, $cComboCharacter)

    Local $sHotKey = _HotKeysGet($sButton)

    GUICtrlSetState($cCheckWin, 4)
    GUICtrlSetState($cCheckCtrl, 4)
    GUICtrlSetState($cCheckAlt, 4)
    GUICtrlSetState($cCheckShift, 4)
    If StringInStr($sHotKey, "#") <> 0 Then GUICtrlSetState($cCheckWin, 1)
    If StringInStr($sHotKey, "^") <> 0 Then GUICtrlSetState($cCheckCtrl, 1)
    If StringInStr($sHotKey, "!") <> 0 Then GUICtrlSetState($cCheckAlt, 1)
    If StringInStr($sHotKey, "+") <> 0 Then GUICtrlSetState($cCheckShift, 1)

    $sHotKey = StringReplace($sHotKey, "#", "")
    $sHotKey = StringReplace($sHotKey, "^", "")
    $sHotKey = StringReplace($sHotKey, "!", "")
    $sHotKey = StringReplace($sHotKey, "+", "")

    $sHotKey = StringLower($sHotKey)

    If $sHotKey <> "" Then
        If StringLen($sHotKey) > 1 Then Return (SetError(-1, 0, ""))
        ConsoleWrite($sHotKey & @CRLF)
        If Asc($sHotKey) < 97 Or Asc($sHotKey) > 122 Then Return (SetError(-2, 0, ""))
    EndIf

    Local $iIndex = _GUICtrlComboBox_SelectString($cComboCharacter, $sHotKey)

    Return (1)

EndFunc   ;==>_HotKeysUpdateSettingsGuiControls

Func _HotKeysGet($sButton)

    Local $sHotKey = IniRead(@ScriptDir & "\config.ini", $sButton, "Hotkey", "*")
    If @error Or $sHotKey = "*" Then Return (SetError(-1, 0, "{EMPTY}"))

    Return ($sHotKey)

EndFunc   ;==>_HotKeysGet

Func _HotKeysQuickDisable($bDisable = True)

    If $bDisable = True Then
        HotKeySetEx("{XClick1}", "_FuncDummy", 1)
        HotKeySetEx("{XClick2}", "_FuncDummy", 1)
        HotKeySetEx("{XDClick1}", "_FuncDummy", 1)
        HotKeySetEx("{XDClick2}", "_FuncDummy", 1)
    Else
        HotKeySetEx("{XClick1}", "")
        HotKeySetEx("{XClick2}", "")
        HotKeySetEx("{XDClick1}", "")
        HotKeySetEx("{XDClick2}", "")
    EndIf

EndFunc   ;==>_HotKeysQuickDisable

Func _HotKeysSaveToFile($sMouseButton, $sString)

    IniWrite(@ScriptDir & "\config.ini", $sMouseButton, "Hotkey", $sString)
    Return (1)

EndFunc   ;==>_HotKeysSaveToFile

Func _HotKeysSet()

    Local $sHotKey = _HotKeysGet("Back")
    If $sHotKey <> "{EMPTY}" Then _HotKeysAssign("Back", $sHotKey)
    $sHotKeyBack = $sHotKey

    $sHotKey = _HotKeysGet("Forward")
    If $sHotKey <> "{EMPTY}" Then _HotKeysAssign("Forward", $sHotKey)
    $sHotKeyForward = $sHotKey

    Return (1)

EndFunc   ;==>_HotKeysSet

Func _MouseKeyModifierTrayCreate()

    Local $aArray[8] = [7]

    $aArray[1] = TrayCreateItem("Settings")
    $aArray[2] = TrayCreateMenu("Behaviour")
    $aArray[3] = TrayCreateItem("Standard", $aArray[2])
    $aArray[4] = TrayCreateItem("Custom", $aArray[2])
    TrayCreateItem("", $aArray[2])
    $aArray[5] = TrayCreateItem("Set at Startup", $aArray[2])
    $aArray[6] = TrayCreateItem("Quick disable")
    $aArray[7] = TrayCreateItem("Exit")

    Return ($aArray)

EndFunc   ;==>_MouseKeyModifierTrayCreate

Func _MouseKeyModifierSettingsGuiCreate()

    Local $aArray[11] = [10]

    $aArray[1] = GUICreate("Settings", 276, 171)
    $aArray[2] = GUICtrlCreateCombo("", 20, 19, 236, 21, BitOR(0x0003, 0x00200000))
    GUICtrlSetData(-1, "Back|Forward")
    $aArray[3] = GUICtrlCreateCheckbox("Win", 20, 54, 38, 20)
    $aArray[4] = GUICtrlCreateCheckbox("Ctrl", 65, 54, 38, 20)
    $aArray[5] = GUICtrlCreateCheckbox("Alt", 110, 54, 38, 20)
    $aArray[6] = GUICtrlCreateCheckbox("Shift", 155, 54, 41, 20)
    GUICtrlCreateLabel("", 20, 87, 237, 1, 0x10, -1)
    GUICtrlSetBkColor(-1, "-2")
    $aArray[7] = GUICtrlCreateCombo("", 207, 53, 50, 21, BitOR(0x0003, 0x00200000))
    GUICtrlSetData(-1, _AlphabetGenerate())
    $aArray[8] = GUICtrlCreateCheckbox("Disable button", 96, 100, 86, 20)
    $aArray[9] = GUICtrlCreateButton("Save", 20, 134, 76, 25)
    $aArray[10] = GUICtrlCreateButton("Cancel", 181, 134, 76, 25)

    Return ($aArray)

EndFunc   ;==>_MouseKeyModifierSettingsGuiCreate

Func _AlphabetGenerate($sSeparator = "|")

    Local $sReturn = ""
    Local $i

    For $i = 97 To 122
        $sReturn &= Chr($i)
        If $i <> 122 Then $sReturn &= $sSeparator
    Next
    ConsoleWrite($sReturn & @CRLF)
    Return ($sReturn)

EndFunc   ;==>_AlphabetGenerate

Func HotKeySetEx($hotkey, $fun, $block = 1) ; default 1 block 0 intercept allow normal behavour and only for mouse events
    ; if the the hot key name contains the word CLICK then its a mouse button.
    If StringInStr(StringUpper($hotkey), "CLICK") > 0 Then ; Mouse hot key
        Dim $mouseHotKey ; local
        $mouseHotKey = $hotkey
        $mouseHotKey = StringReplace($mouseHotKey, "{", "") ; remove { } for mousetrap interface
        $mouseHotKey = StringReplace($mouseHotKey, "}", "")
        If $fun = "" Then
            _MouseTrapEvent($mouseHotKey) ; deregister
        Else
            _MouseTrapEvent($mouseHotKey, $fun, $block) ; 1 = block action and redirect to $fun
        EndIf
    Else
        HotKeySet($hotkey, $fun) ; normal AutoIt
    EndIf
EndFunc   ;==>HotKeySetEx

Func getLastHotKey() ; call this in your function.  Equivalent to @HotKeyPressed see example script
    setLastHotKey()
    Return $gLastHotKeyPressed ;
EndFunc   ;==>getLastHotKey

Func getLastHotKeyType() ; call this in your function.  Optional if you want type KEYBOARD or MOUSE
    setLastHotKey()
    Return $gLastHotKeyType ;
EndFunc   ;==>getLastHotKeyType

Func setLastHotKey() ;
    Dim $sLastMouseEventPressed
    $sLastMouseEventPressed = __MouseTrapEvent_getLastMouseEventPressed()
    If $sLastMouseEventPressed <> "" Then
        $gLastHotKeyPressed = "{" & $sLastMouseEventPressed & "}"
        $gLastHotKeyType = "Mouse"
    Else
        $gLastHotKeyPressed = @HotKeyPressed
        $gLastHotKeyType = "Keyboard"
    EndIf
    Return $gLastHotKeyPressed ;
EndFunc   ;==>setLastHotKey

; #FUNCTION# ====================================================================================================
; Name...........:  _MouseTrapEvent
; Description....:  Set an events handler (a hook) for Mouse device based on MouseSetEvent.udf.
; Syntax.........:  _MouseTrapEvent($iEvent, $sFuncName = "", $hTargetWnd = 0, $iBlockDefProc = -1, $vParam = "")
; Parameters.....:  $sEvent         - The event to set, here is the list of
;                   supported event stings:- Case InSensitive!
;
;                   single clicks
;                   LClick - left button click (Primary)
;                   MClick - middle button click (Wheel click)
;                   RClick - right button click (Secondary)
;                   XClick1 - Xtra button 1 click (usually 'back navigaton')
;                   XClick2 - Xtra button 2 click (usually 'forward navigaton')

;                   double clicks
;                   LDClick - left button (Primary)
;                   MDClick - middle button  (Wheel click)
;                   RDClick - right button  (Secondary)
;                   XDClick1 - Xtra button 1  (usually 'back navigaton')
;                   XDClick2 - Xtra button 2  (usually 'forward navigaton')

;                   psuedo double clicks ('chords') -
;                   XClick12 - Xtra button 1&2 pressed at the same time.
;
;                   OTHER EVENTS you'll have to work out yourself eg mouse wheel scroll - see code.

;                   $sFuncName      - [Optional] Function name to call when the event is triggered.
;                                       If this parameter is empty string ("") or omited, the function will *unset* the $iEvent.
;
;                   $iBlockDefProc  - [Optional] Defines if the up event should be blocked (actualy block the mouse action).
;                                       If this parameter =
;                                       -1 (default), user defined event function defines whether to block or not
;                                        1 (call function and block)
;                                        0 (call function and continue normal mouse behaviour).
;                                     Note for all click and double click events the down event is always blocked to prevent hanging.
;
;
;                   $vParam         - [Optional] Parameter to pass to the event function ($sFuncName).
;
; Return values..:  Success         - If the event is set in the first time, or when the event is unset properly, the return is 1,
;                                       if it's set on existing event, the return is 2.
;                   Failure         - Returns 0 on UnSet event mode when there is no set events yet.
; Author.........:  credits G.Sandler (Mr)CreatoR
; Remarks........:
;                   2) Blocking of $sFuncName function by window messages with commands
;                     such as "Msgbox()" can lead to unexpected behavior, the return to the system should be as fast as possible!
; Related........:  MouseSetEvent.udf
; Link...........:
; Example........:  Yes.
; ===============================================================================================================
Func _MouseTrapEvent($iEvent, $sFuncName = "", $iBlockDefProc = -1, $vParam = "")
    Local $i
    Local $iUserEventCount = 0
    Local $hTargetWnd = 0 ; not used
    $iEvent = StringReplace(StringUpper($iEvent), "CLICK", "Click") ; make case insensitive, to do Drag and Wheel and Up Down

    If $sFuncName = "" Then ;Unset Event
        If $a__MSOE_Events[0][0] < 1 Then
            Return 0
        EndIf

        Local $aTmp_Mouse_Events[1][1] = [[0]]

        For $i = 1 To $a__MSOE_Events[0][0]
            ; keep events that don't match or internal dummy events used for double clicks.
            If $a__MSOE_Events[$i][0] <> $iEvent Or $a__MSOE_Events[$i][1] = $MOUSETRAPEVENT_DUMMY Then
                $aTmp_Mouse_Events[0][0] += 1
                ReDim $aTmp_Mouse_Events[$aTmp_Mouse_Events[0][0] + 1][5]

                $aTmp_Mouse_Events[$aTmp_Mouse_Events[0][0]][0] = $a__MSOE_Events[$i][0]
                $aTmp_Mouse_Events[$aTmp_Mouse_Events[0][0]][1] = $a__MSOE_Events[$i][1]
                $aTmp_Mouse_Events[$aTmp_Mouse_Events[0][0]][2] = $a__MSOE_Events[$i][2]
                $aTmp_Mouse_Events[$aTmp_Mouse_Events[0][0]][3] = $a__MSOE_Events[$i][3]
                $aTmp_Mouse_Events[$aTmp_Mouse_Events[0][0]][4] = $a__MSOE_Events[$i][4]
                If $a__MSOE_Events[$i][1] <> $MOUSETRAPEVENT_DUMMY Then
                    $iUserEventCount += 1
                EndIf
            EndIf
        Next

        $a__MSOE_Events = $aTmp_Mouse_Events


        If $iUserEventCount < 1 Then
            __MouseTrapEvent_Close()
        EndIf

        Return 1
    EndIf

    ;First event
    If $a__MSOE_Events[0][0] < 1 Then
        ;Register callback
        $hKey_Proc = DllCallbackRegister("_MouseTrapEvent_MouseProc", "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)

    EndIf


    ;Search thru events, and if the event already set, we just (re)set the new function and other parameters
    For $i = 1 To $a__MSOE_Events[0][0]
        If $a__MSOE_Events[$i][0] = $iEvent Then
            If $sFuncName = $MOUSETRAPEVENT_DUMMY Then
                ; event already handled by user - no need for dummy event
                Return 1
            EndIf
            $a__MSOE_Events[$i][0] = $iEvent
            $a__MSOE_Events[$i][1] = $sFuncName
            $a__MSOE_Events[$i][2] = $hTargetWnd
            $a__MSOE_Events[$i][3] = $iBlockDefProc
            $a__MSOE_Events[$i][4] = $vParam

            Return 2
        EndIf
    Next

    $a__MSOE_Events[0][0] += 1
    ReDim $a__MSOE_Events[$a__MSOE_Events[0][0] + 1][5]

    $a__MSOE_Events[$a__MSOE_Events[0][0]][0] = $iEvent
    $a__MSOE_Events[$a__MSOE_Events[0][0]][1] = $sFuncName
    $a__MSOE_Events[$a__MSOE_Events[0][0]][2] = $hTargetWnd
    $a__MSOE_Events[$a__MSOE_Events[0][0]][3] = $iBlockDefProc
    $a__MSOE_Events[$a__MSOE_Events[0][0]][4] = $vParam

    ; if double click event - attempt to register a dummmy event for single click if one dosen't exist- to prevent hanging
    If StringInStr($iEvent, "DClick") > 0 Then
        _MouseTrapEvent(StringReplace($iEvent, "DClick", "Click"), $MOUSETRAPEVENT_DUMMY, 0, 0)
    EndIf
    ; if multi button click event - attempt to register a dummmy single click event for each button - to prevent hanging
    If $iEvent = "XClick12" Then
        _MouseTrapEvent("XClick1", $MOUSETRAPEVENT_DUMMY, 0, 0)
        _MouseTrapEvent("XClick2", $MOUSETRAPEVENT_DUMMY, 0, 0)
    EndIf

    Return 1
EndFunc   ;==>_MouseTrapEvent

Func _MouseTrapEvent_Dummy()
    ; dummy function for unregistered click events of double clicks
    Return 0;
EndFunc   ;==>_MouseTrapEvent_Dummy

Func _MouseTrapEvent_MouseProc($nCode, $wParam, $lParam)
    Local $info, $mouseData, $time, $timeDiff
    If $nCode < 0 Then
        $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
                "int", $nCode, "ptr", $wParam, "ptr", $lParam)
        Return $ret[0]
    EndIf

    $info = DllStructCreate($MSLLHOOKSTRUCT, $lParam)
    $mouseData = DllStructGetData($info, 3)
    $time = DllStructGetData($info, 5)
    $timeDiff = $time - $currentEvent[1]
    Select
        Case $wParam = $WM_MOUSEMOVE
            ;Test for Drag in here
            If $currentEvent[0] <> "LDrag" Or $currentEvent[0] <> "LRDrag" Or $currentEvent[0] <> "LMDrag" Then
                If $iLBUTTONDOWN = 1 Then
                    $currentEvent[0] = "LDrag"
                    If $iRBUTTONDOWN = 1 Then
                        $currentEvent[0] = "LRDrag"
                        $LRDrag = 2
                    EndIf
                EndIf
            EndIf
            If $currentEvent[0] <> "RDrag" Or $currentEvent[0] <> "RMDrag" Or $currentEvent[0] <> "LRDrag" Then
                If $iRBUTTONDOWN = 1 Then
                    $currentEvent[0] = "RDrag"
                EndIf
            EndIf

            If $currentEvent[0] <> "MDrag" Then
                If $iMBUTTONDOWN = 1 Then
                    $currentEvent[0] = "MDrag"
                    $currentEvent[1] = $time
                EndIf
            EndIf

            If $iRBUTTONDOWN = 1 And $iMBUTTONDOWN = 1 And $currentEvent[0] <> "RMDrag" Then
                $RMDrag = 2
                $currentEvent[0] = "RMDrag"
                $currentEvent[1] = $time
            EndIf

            If $iLBUTTONDOWN = 1 And $iMBUTTONDOWN = 1 And $currentEvent[0] <> "LMDrag" Then
                $LMDrag = 2
                $currentEvent[0] = "LMDrag"
                $currentEvent[1] = $time
            EndIf

        Case $wParam = $WM_MOUSEWHEEL
            If _WinAPI_HiWord($mouseData) > 0 Then
                ;Wheel Up
                $currentEvent[0] = "WheelUp"
                $currentEvent[1] = $time
            Else
                ;Wheel Down
                $currentEvent[0] = "WheelDown"
                $currentEvent[1] = $time
            EndIf

        Case $wParam = $WM_LBUTTONDOWN
            ;Register Button Down, check for Right/Left
            If $currentEvent[0] = "RClick" Then
                $LRClickStatus = 1
            EndIf

            $iLBUTTONDOWN = 1
            $currentDownEvent[0] = 'LClick'



        Case $wParam = $WM_LBUTTONUP
            ;Update $iLBUTTONDOWN
            $iLBUTTONDOWN = 0
            $currentDownEvent[0] = ''

            ;Test for Right/Left Click
            If $RLClickStatus = 1 And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "RLClick"
                $currentEvent[1] = $time
            EndIf
            If $lastEvent = "LClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "LDClick"
                $currentEvent[1] = $time
            EndIf
            ;Test for Drops
            If $currentEvent[0] = "LDrag" Then
                $currentEvent[0] = "LDrop"
                $currentEvent[1] = $time
            EndIf

            If $LRDrag = 2 And $iRBUTTONDOWN = 1 Then
                $LRDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LRDrag = 1 And $iRBUTTONDOWN = 0 Then
                $currentEvent[0] = "LRDrop"
                $currentEvent[1] = $time
                $LRDrag = 0
            EndIf



            If $LMDrag = 2 And $iMBUTTONDOWN = 1 Then
                $LMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $LMDrag = 1 And $iMBUTTONDOWN = 0 Then
                $currentEvent[0] = "LMDrop"
                $currentEvent[1] = $time
                $LMDrag = 0
            EndIf

            ;Set LClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "LClick"
                $currentEvent[1] = $time
            EndIf

            ;Negate $LRClickStatus
            $RLClickStatus = 0



        Case $wParam = $WM_RBUTTONDOWN
            ;Register Button Down
            If $currentEvent[0] = "LClick" Then
                $RLClickStatus = 1
            EndIf
            $iRBUTTONDOWN = 1
            $currentDownEvent[0] = 'RClick'

        Case $wParam = $WM_RBUTTONUP
            ;Test for Left, Right, and Right Doubleclick here
            ;Update $iRBUTTONDOWN
            $iRBUTTONDOWN = 0
            $currentDownEvent[0] = '';

            ;Test for Right/Left Click
            If $LRClickStatus = 1 And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "LRClick"
                $currentEvent[1] = $time
            EndIf


            If $lastEvent = "RClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "RDClick"
                $currentEvent[1] = $time
            EndIf
            ;Test for Drops
            If $currentEvent[0] = "RDrag" Then
                $currentEvent[0] = "RDrop"
                $currentEvent[1] = $time
            EndIf

            If $LRDrag = 2 And $iLBUTTONDOWN = 1 Then
                $LRDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LRDrag = 1 And $iLBUTTONDOWN = 0 Then
                $currentEvent[0] = "LRDrop"
                $currentEvent[1] = $time
                $LRDrag = 0
            EndIf



            If $RMDrag = 2 And $iMBUTTONDOWN = 1 Then
                $RMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $RMDrag = 1 And $iMBUTTONDOWN = 0 Then
                $currentEvent[0] = "RMDrop"
                $currentEvent[1] = $time
                $RMDrag = 0
            EndIf

            ;Set LClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "RClick"
                $currentEvent[1] = $time
            EndIf

            ;Negate $LRClickStatus
            $LRClickStatus = 0


        Case $wParam = $WM_MBUTTONDOWN
            ;Register Button Down
            $iMBUTTONDOWN = 1
            $currentDownEvent[0] = 'MClick'

        Case $wParam = $WM_MBUTTONUP
            ;Test for Middle Double Click here
            ;Update $iRBUTTONDOWN
            $iMBUTTONDOWN = 0
            $currentDownEvent[0] = ''

            ;Test for Right/Left Click
            If $lastEvent = "MClick" And ($timeDiff) < $doubleClickTime Then
                $currentEvent[0] = "MDClick"
                $currentEvent[1] = $time
            EndIf
            ;Test for Drops
            If $currentEvent[0] = "MDrag" Then
                $currentEvent[0] = "MDrop"
                $currentEvent[1] = $time
            EndIf

            If $LMDrag = 2 And $iLBUTTONDOWN = 1 Then
                $LMDrag = 1 ; Denote $LRDrag as still having one button clicked, need to register the drop on RButton up
            EndIf

            If $LMDrag = 1 And $iLBUTTONDOWN = 0 Then
                $currentEvent[0] = "LMDrop"
                $currentEvent[1] = $time
                $LMDrag = 0
            EndIf



            If $RMDrag = 2 And $iRBUTTONDOWN = 1 Then
                $RMDrag = 1 ; Denote $LMDrag as still having one button clicked, need to register the drop on MButton up
            EndIf

            If $RMDrag = 1 And $iRBUTTONDOWN = 0 Then
                $currentEvent[0] = "RMDrop"
                $currentEvent[1] = $time
                $RMDrag = 0
            EndIf

            ;Set MClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                $currentEvent[0] = "MClick"
                $currentEvent[1] = $time
            EndIf
        Case $wParam = $WM_XBUTTONDOWN
            $iXBUTTONDOWNNumber = _WinAPI_HiWord($mouseData)

            $currentDownEvent[0] = 'XClick' & $iXBUTTONDOWNNumber

        Case $wParam = $WM_XBUTTONUP

            Local $iXbuttonNumber = _WinAPI_HiWord($mouseData)


            If ($lastEvent = "XClick1" Or $lastEvent = "XClick2") And ($timeDiff) < $doubleClickTime Then
                If StringRight($lastEvent, 1) = $iXBUTTONDOWNNumber Then
                    $currentEvent[0] = "XDClick" & $iXbuttonNumber
                    $currentEvent[1] = $time
                Else
                    $currentEvent[0] = "XClick12" ; both X buttons pressed simultaneously
                    $currentEvent[1] = $time

                EndIf
            EndIf


            ;Set XClick if other events haven't fired
            If $currentEvent[1] <> $time Then
                If $iXbuttonNumber > 0 Then
                    ;standard win 2000+ Xtra button pressed, append 1 or 2 to event name
                    $currentEvent[0] = "XClick" & $iXbuttonNumber
                    $currentEvent[1] = $time

                EndIf
            EndIf


            $iXBUTTONDOWNNumber = 0 ; reset
            $currentDownEvent[0] = ''
    EndSelect

    If $currentEvent[0] <> "" Then
        $lastEvent = $currentEvent[0]
    EndIf
    If __MouseTrapEvent_Remap($currentEvent[0]) = 1 Then
        Return 1;
    EndIf

    $ret = DllCall("user32.dll", "long", "CallNextHookEx", "hwnd", $hM_Hook[0], _
            "int", $nCode, "ptr", $wParam, "ptr", $lParam)

    Return $ret[0]
EndFunc   ;==>_MouseTrapEvent_MouseProc

; local function - not user callable
Func __MouseTrapEvent_Remap($sEvent)
    ;search for event to block
    For $i = 1 To $a__MSOE_Events[0][0]

        ;Handle / block down events - done to prevent lock ups
        If $a__MSOE_Events[$i][0] = $currentDownEvent[0] Then

            Return 1; block handle event

        EndIf



        ; handle click - up events.
        If $a__MSOE_Events[$i][0] = $sEvent Then
            ;Handle events

            Local $iBlockDefProc_Ret = $a__MSOE_Events[$i][3]

            Local $sFuncName = $a__MSOE_Events[$i][1]

            $iRet = Call($sFuncName, $sEvent, $a__MSOE_Events[$i][4])

            If @error Then
                $iRet = Call($sFuncName, $sEvent)

                If @error Then
                    $iRet = Call($sFuncName)
                EndIf
            EndIf


            If $iBlockDefProc_Ret = -1 Then
                $iBlockDefProc_Ret = $iRet
            EndIf

            $currentEvent[0] = ""
            Return $iBlockDefProc_Ret ;Block default processing (or not :))
        EndIf
    Next
    Return 0 ; don't bypass
EndFunc   ;==>__MouseTrapEvent_Remap

; call this from HotKeySetEx for mouse hotkeys.
Func __MouseTrapEvent_getLastMouseEventPressed()

    For $i = 1 To $a__MSOE_Events[0][0]
        Local $sFuncName = $a__MSOE_Events[$i][1]
        ; If current event a registered hotkey then it will be the last pressed
        If $a__MSOE_Events[$i][0] = $currentEvent[0] And $sFuncName <> "" And $sFuncName <> $MOUSETRAPEVENT_DUMMY Then
            Return $currentEvent[0]; hot key found
        EndIf
    Next

    Return ""

EndFunc   ;==>__MouseTrapEvent_getLastMouseEventPressed

; called this to shut down without having to deregister all events.
Func __MouseTrapEvent_Close()

    DllCall("user32.dll", "int", "UnhookWindowsHookEx", "hwnd", $hM_Hook[0])
    $hM_Hook[0] = 0
    DllCallbackFree($hKey_Proc)
    $hKey_Proc = 0

    ; clear all events
    Dim $a__MSOE_Events[1][1]

EndFunc   ;==>__MouseTrapEvent_Close

Func __MouseTrapEvent_GetDoubleClickData()
    Local $aRet[3] = _
            [ _
            RegRead('HKEY_CURRENT_USER\Control Panel\Mouse', 'DoubleClickSpeed'), _
            RegRead('HKEY_CURRENT_USER\Control Panel\Mouse', 'DoubleClickWidth'), _
            RegRead('HKEY_CURRENT_USER\Control Panel\Mouse', 'DoubleClickHeight') _
            ]

    Local $aGDCT = DllCall('User32.dll', 'uint', 'GetDoubleClickTime')

    If Not @error And $aGDCT[0] > 0 Then
        $aRet[0] = $aGDCT[0]
    EndIf

    Return $aRet
EndFunc   ;==>__MouseTrapEvent_GetDoubleClickData

 

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

×
×
  • Create New...