Jump to content

mouse chording (shortcuts with mouse)


Recommended Posts

Hey guys,

I'm writing a little program, that runs in background. It's supposed to run a function when I:
- hold down right mouse button for 1sec
- hold down right mouse + left mouse (mouse chording)

For example: hold down right mouse button for 1sec > delete current line in notepad.

Now, the problem is: I can detect when the rightclick is pressed.
BUT: the rightclick is already executed (in this case: note shows its contextmenu...)

How can I "catch up" the original input, dismiss it/ replace it, to execute another command (in this case press "delete")
 

#include <Misc.au3>

While 1

    If _IsPressed(2) Then
        MsgBox(64, "", "Rightclick")
        
    EndIf

WEnd

 

Edited by atvaxn
Link to post
Share on other sites

hey, thanks a lot for the link. Its exactly what I'm looking for, except I still can't figure out how to combine both together. I downloaded the MouseOnEvent_2.4.zip from your link.
Would be nice if you could give me a little kick :)

#include <Misc.au3>
#include <Process.au3>
#include <MouseOnEvent.au3>



; catch Events
; ########################################################################################################################
_MouseSetOnEvent($MOUSE_PRIMARYDOWN_EVENT, "__MAIN", 0, 0)
_MouseSetOnEvent($MOUSE_SECONDARYDOWN_EVENT, "__MAIN", 0, 0)        
_MouseSetOnEvent($MOUSE_SECONDARYUP_EVENT, "__MAIN", 0, 0)
While 1
WEnd


; __MAIN
; ########################################################################################################################
Func __MAIN()
    Switch _ProcessGetName(WinGetProcess(WinGetHandle("[active]")))


        Case "notepad.exe"
            _MouseSetOnEvent($MOUSE_PRIMARYDOWN_EVENT, "__MAIN", 0, 0)
            _MouseSetOnEvent($MOUSE_SECONDARYDOWN_EVENT, "__MAIN", WinGetHandle("[active]"), 1)
            _MouseSetOnEvent($MOUSE_SECONDARYUP_EVENT, "__MAIN", WinGetHandle("[active]"), 1)

            ; NOT WORKING
            ;Local $sInit = TimerInit()
            ;While _IsPressed(2)
                ;ToolTip("AA: " & TimerDiff($sInit))
            ;WEnd

        Case Else
            _MouseSetOnEvent($MOUSE_PRIMARYDOWN_EVENT, "__MAIN", 0, 0)
            _MouseSetOnEvent($MOUSE_SECONDARYDOWN_EVENT, "__MAIN", 0, 0)        
            _MouseSetOnEvent($MOUSE_SECONDARYUP_EVENT, "__MAIN", 0, 0)
            ToolTip(WinGetTitle("[active]"))
    EndSwitch
    
    Return $MOE_BLOCKDEFPROC
EndFunc

 

And this is my original code, which basically works perfect, except the problem, that the original click is still passed to the target application:

#include <Misc.au3>
#include <Process.au3>


While 1

    If _IsPressed(2) Then

        Local $sInit = TimerInit()
        Switch _ProcessGetName(WinGetProcess(WinGetTitle("[active]")))

            Case "notepad.exe"
                While _IsPressed(2)
                    If _IsPressed(1) Then
                        MsgBox(64, "CHORDINGmode", "Mouse 2 + Mouse1 clicked together")
                        continueloop 2
                    EndIf
                WEnd
                
                If TimerDiff($sInit) < 175 Then
                    MsgBox(64, "HOLDmode", "0-175 ms")

                ElseIf TimerDiff($sInit) >= 175 Then
                    MsgBox(64, "HOLDmode", "> 175ms")

                EndIf
        
        EndSwitch
    EndIf

sleep(10)
WEnd


 

Edited by atvaxn
Link to post
Share on other sites

thank you so much junkew. I tried all night that WinAPI and it seem to be exactly what I'm looking for. T H A N K S !!!!
I want to create mouse chordings, just like described in https://en.wikipedia.org/wiki/Mouse_chording
I
'm really surprised, that there seems to be no forum threads here about this very interesting topic...

Now, after hours of googeling + trial & error 😄, I finally have some early results. It works so far, at least like what I expect from it.

- custom command when holding right click > 200ms and >700ms
- custom command when holding right click + left click (mouse chording)
- custom command when holding right click + double click = sometimes it works, sometimes not.... 🤔
- the context-menu/normal rightclick is very slow... :(

I'm still not sure about the performance (CPU-usage etc.), because the cursor got laggy sometimes when tried out different solutions.
Especially, when putting a sleep() command.
However, I'm still too unexperienced to detect weak spots.


Would be cool if you can have a look over it and tell me some weak spots or some hints for speed improvements?
thank you guys :)

 

#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <Misc.au3>
#include <Process.au3>
HotKeySet('{ESC}', '_Close')



; ########################################################################################################################
Global $LEFTmbstate="up", $RIGHTmbstate="up", $sInit
Global $GiTimerINIT = 0, $GiTimerCalc = 0, $GTempSleep = 0
Global $hHook
Local $hFunc, $pFunc, $hMod


$hFunc = DllCallbackRegister('_MouseProc', 'lresult', 'int;int;int')
$pFunc = DllCallbackGetPtr($hFunc)
$hMod = _WinAPI_GetModuleHandle(0)
$hHook = _WinAPI_SetWindowsHookEx($WH_MOUSE_LL, $pFunc, $hMod)


Global $DblClk_Speed = RegRead("HKCU\Control Panel\Mouse", "DoubleClickSpeed") 
If @error Then $DblClk_Speed = 500
Global $TimerDBLCLK = 0


While 1
    Sleep(50)
WEnd



; Permanently called when mouse changes its position
; ########################################################################################################################
Func _MouseProc($iCode, $iwParam, $ilParam)
    If $iCode < 0 Then Return _WinAPI_CallNextHookEx($hHook, $iCode, $iwParam, $ilParam)

    Switch $iwParam

        ; ########################################################################################
        Case $WM_LBUTTONDOWN
            $LEFTmbstate = "down"
            If $GTempSleep = 1 Then Return

            If $RIGHTmbstate = "down" Then
                If __DBLCHECK() Then
                    __ACTION(TimerDiff($sInit), "chordingRIGHT+LEFTdbclk")
                EndIF
                __ACTION(TimerDiff($sInit), "chordingRIGHT+LEFT")
            EndIf

        ; ########################################################################################
        Case $WM_RBUTTONDOWN
            $RIGHTmbstate = "down"
            If $GTempSleep = 1 Then Return

            $GiTimerINIT = TimerInit()
            AdlibRegister('_Timer', 10)
            Return 1

        ; ########################################################################################
        Case $WM_RBUTTONUP
            $RIGHTmbstate = "up"
            If $GTempSleep = 1 Then Return

            __ACTION($GiTimerCalc, "holdingLRIGHT")


    EndSwitch
    
    Return _WinAPI_CallNextHookEx($hHook, $iCode, $iwParam, $ilParam)

EndFunc   ;==>_MouseProc




Func __ACTION($iSeconds, $iMode)

AdlibUnRegister('_Timer')

Switch _ProcessGetName(WinGetProcess(WinGetTitle("[active]")))

    ; NOTEPAD
    ; ########################################################################################################
    Case "notepad.exe"
        
        If $iMode = "chordingRIGHT+LEFT" Then
            $GTempSleep = 1
            __INFOshow("chording right > left: duplicate current line", $iSeconds)
            $GTempSleep = 0

        ElseIf $iMode = "holdingLRIGHT" Then
            If $iSeconds < 200 Then
                $GTempSleep = 1
                ; __INFOshow("NORMAL rightclick < 200 ms", $iSeconds)
                MouseClick($MOUSE_CLICK_RIGHT)
                $GTempSleep = 0

            ElseIf $iSeconds >= 200 Then
                $GTempSleep = 1
                __INFOshow("HOLDING rightclick > 200 ms: delete current line", $iSeconds)
                $GTempSleep = 0
            EndIf

        ElseIf $iMode = "chordingRIGHT+LEFTdbclk" Then
            $GTempSleep = 1
            __INFOshow("chordingRIGHT+LEFTdbclk: convert line to comment", $iSeconds)
            $GTempSleep = 0

        ElseIf $iMode = "700extended" Then
            $GTempSleep = 1
            __INFOshow("command fired up after 700 ms", $iSeconds)
            $GTempSleep = 0
        EndIf       

EndSwitch

EndFunc



Func __INFOshow($sMSG, $iTime)
    ; MsgBox(64, $sMSG, $iTime)
    Tooltip($sMSG & @CRLF & $iTime)
EndFunc


Func _Close()
    _WinAPI_UnhookWindowsHookEx($hHook)
    DllCallbackFree($hHook)
    Exit
EndFunc   ;==>_Close


Func __DBLCHECK()
    If $TimerDBLCLK = 0 Then
        $TimerDBLCLK = TimerInit()
        Return False
    Else
        If TimerDiff($TimerDBLCLK) <= $DblClk_Speed+200 Then
            Return True
        EndIf
        $TimerDBLCLK = TimerInit()
        Return False
    EndIf
EndFunc


Func _Timer()
    $GiTimerCalc = TimerDiff($GiTimerINIT)
    
    ; Hold longer than 700ms
    If $GiTimerCalc > 700 Then
        __ACTION($GiTimerCalc, "700extended")
    EndIf
    
EndFunc

 

Edited by atvaxn
Link to post
Share on other sites
  • atvaxn changed the title to mouse chording (shortcuts with mouse)

As most solutions it depends on which user you are targetting. >98% of the user's only use what they can see.

For mouse chording you have to read the manual and probably behavior would differ per application.

Right mouse and (customized) contextmenu seems to work more intuitive if properly implemented. 

 

Would try your chording with this 😉 

https://hard-drive.net/gaming-mouse-has-more-buttons-than-keyboard/

Link to post
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
  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...