evilC / AutoHotInterception

An AutoHotkey wrapper for the Interception driver
MIT License
707 stars 64 forks source link

How to use subscription mode + key modifiers (shift, ctrl, etc) #68

Closed TheBestPessimist closed 3 years ago

TheBestPessimist commented 3 years ago

I'm trying to change my PgDn key to work as Home.

Background first: I have tried to use context mode to change some keys on my laptop keyboard to other keys (but not for external keyboard). Unfortunately it seems that in context mode, sometimes the original key function runs (idk why, but it happens about 30% of the time). Using Shift/Ctrl/etc. while using the Intercepted keys works ok though.

Actual problem: In subscription mode however, key modifiers don't work.

Example

Do you know how I can achieve modifier handling?


Context mode code:

AHI := new AutoHotInterception()
Fusion15KeyboardId := AHI.GetKeyboardIdFromHandle("ACPI\VEN_MSFT&DEV_0001", 1)
AHIContextManager := AHI.CreateContextManager(Fusion15KeyboardId)

#if AHIContextManager.IsActive
    PgUp::PgDn

    PgDn::Home

    Home::PgUp
#if

Subscription mode code:

AHI := new AutoHotInterception()
Fusion15KeyboardId := AHI.GetKeyboardIdFromHandle("ACPI\VEN_MSFT&DEV_0001", 1)

AHI.SubscribeKey(Fusion15KeyboardId, GetKeySC("PgUp"), true, Func("XmgKeyEventHandler").Bind("PgDn"))
AHI.SubscribeKey(Fusion15KeyboardId, GetKeySC("PgDn"), true, Func("XmgKeyEventHandler").Bind("Home"))
AHI.SubscribeKey(Fusion15KeyboardId, GetKeySC("Home"), true, Func("XmgKeyEventHandler").Bind("PgUp"))

XmgKeyEventHandler(newKey, state)
{
    if(state)
        Send % "{" newKey " down}"
    else
        Send % "{" newKey " up}"
}

The code is all available here: https://github.com/thebestpessimist/autohotkey-scripts/blob/d179395138cc1653cdaca110753294920293854c/XmgFusion15.ahk#L35-L50

TheBestPessimist commented 3 years ago

Ah, I'm sorry for bothering with this, the solution was so simple: I just had to send in Blind mode.

Momen-kh commented 1 week ago

@TheBestPessimist Hi thanks for this post Can I send Ctrl key from my main mouse and another key from my mouse button with InterceptionTapHold method? Please if you could help me here is my code and thanks in advanced `#SingleInstance force

Persistent

WinActivateForce

include

Include

Include

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;id2 := AHI.GetKeyboardId(0x04D9, 0x1203, 1) ;cm2 := AHI.CreateContextManager(id2)

;Return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

If ( WinActive("ahk_exe notepad.exe") && (contex_1.IsActive) )

AHI := new AutoHotInterception()
;AHI.Instance.SendMouseMove(...)
id1 := AHI.GetKeyboardId(0x25A7, 0xFA07)
contex_1 := AHI.CreateContextManager(id1)
Inter_Hold_1 := new InterceptionTapHold(AHI, id1,300 )     ; override holdTime to 300

Inter_Hold_1.Add("2", Func("Func1"), 200 )              ; This is not working
^2::                                                    ; This one working fine
MsgBox, Message_1 here

If

Return ; #IfWinActive ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Function

Func1(isHold, taps, state){

    if (isHold=0) & (taps=1)& (state)
    {
        tooltip, you pressed the function key %A_thishotkey% on the [F23] keyboard
    }

    if (isHold=0) & (taps=2)& (state)
    {
        send,My name is Momen{Space}{Enter}
    }

    if (isHold=0) & (taps=3)& (state)
    {
        send,What is your name?{Space}{Enter}{Enter}
    }

    if (isHold=1) & (taps=1)& (state)
    {
        send,My name is Anas{Space}{Enter}
    }

    if (isHold=1) & (taps=2)& (state)
    {
        send,Nice to meet you{!}{Space}{Enter}
    }

}

`

TheBestPessimist commented 1 week ago

@Momen-kh i no longer use Interception and AutoHotInterception respectively, as the Interception driver's 10 USB devices limitation has proven a giant pain in the ass for me as a laptop user. Can't help you there.

Momen-kh commented 1 week ago

@TheBestPessimist Thanks for your reply are you using another method to control your extra devices? Thanks a lot.

TheBestPessimist commented 1 week ago

Nope. I don't need multiple device control anymore. Gave up on it

Momen-kh commented 1 week ago

@TheBestPessimist Thanks a lot. I wish you luck in finding what you seek.

evilC commented 1 week ago

@Momen-kh Hard to tell what you are doing, there's so much WTF ?!? in that code

#If ( WinActive("ahk_exe notepad.exe") && (contex_1.IsActive) )
; All the code below is unreachable.
; contex_1.IsActive above cannot ever be true, because contex_1 is declared below
AHI := new AutoHotInterception()
id1 := AHI.GetKeyboardId(0x25A7, 0xFA07)
contex_1 := AHI.CreateContextManager(id1)

Declaring AHI inside an #if block ?!?!? then declaring contex_1 inside the #if block that only executes if it is already true ?!?!

Inter_Hold_1.Add("2", Func("Func1"), 200 ) ; This is not working
Of course it won't work, because you declared Inter_Hold_1 in a #if block that could not ever execute

What you are doing is essentially equivalent to

execute_code := 0
if (execute_code){
   ; Can never ever run
   execute_code := 1
   AHI := ...
}
Momen-kh commented 1 week ago

@evilC I am sorry about that mess. I don’t know coding. All I want to do is to customise my mouse buttons to use it for graphic design apps. I need mouse button to work with your InterceptionTapHold and with ctrl key also If you could help me please I will be thankful Sorry for disturbing.

evilC commented 1 week ago

If I understood what you were trying to do, I could maybe help...

Momen-kh commented 1 week ago

Thanks a lot OK. Before I was using morse function to control press-and-hold patterns for keys in my mouse ( a mouse with 12 buttons) but the problem was mouse buttons send (1 - 10 ) which conflict with keys in my keyboard. I found your method (InterceptionTapHold ) and I'm trying to make it work the same as Autohotkey morse method. Now I have two problems: 1) I want to make (Func1) work only with active window 2) I want to use a mouse button beside (ctrl key in my main keyboard - if that is possible) Please see (the messy code) and forgive me. and also forgive me about my bad English it is not my native language. Thanks a lot for helping me.

`#SingleInstance force

Persistent

WinActivateForce

include

Include

Include

If ( WinActive("ahk_exe notepad.exe")) ;1) not working ( Please help )

AHI := new AutoHotInterception()

id1 := AHI.GetKeyboardId(0x25A7, 0xFA07)
Inter_Hold_1 := new InterceptionTapHold(AHI, id1,300 )     
Inter_Hold_1.Add("2", Func("Func1"), 200 ) 

^2::             ; 2) not working  ( Please help )
MsgBox, Message_6

If

Return ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;Function

Func1(isHold, taps, state) { if (isHold=0) & (taps=1)& (state) { send,Message_1 }

    if (isHold=0) & (taps=2)& (state)
    {
        send,Message_2
    }

    if (isHold=0) & (taps=3)& (state)
    {
        send,Message_3
    }

    if (isHold=1) & (taps=1)& (state)
    {
        send,Message_4
    }

    if (isHold=1) & (taps=2)& (state)
    {
        send,Message_5
    }

}

`

evilC commented 6 days ago

So you want to use CTRL+2 for tap and hold, not just 2?

Momen-kh commented 6 days ago

No sir. I want CTRL+2 for normal function. like send a message or somehing and 2 only for press-and-hold patterns

evilC commented 6 days ago

To use CTRL+2, you could do something like this: (Untested code)

; Demonstrates Interception Subscription Mode with TapHoldManager
#SingleInstance force
; Use these includes if you placed the contents of the TapHoldManager and AutoHotInterception Lib folders in the AHK lib folder (My Documents\AutoHotkey\Lib)
;#include <AutoHotInterception>
;#include <InterceptionTapHold>
;#include <TapHoldManager>

; Use these includes if you placed the contents of the TapHoldManager and AutoHotInterception Lib folders in a lib folder next to this script
; ie copy the AutoHotInterception Lib folder into the TapHoldManager Lib folder
#include Lib\AutoHotInterception.ahk
#include Lib\InterceptionTapHold.ahk
#include Lib\TapHoldManager.ahk

AHI := new AutoHotInterception()
;keyboard1Id := AHI.GetKeyboardId(0x03EB, 0xFF02)
;keyboard1Id := AHI.GetDeviceIdFromHandle(false, "HID\VID_03EB&PID_FF02&REV_0008&MI_03")
keyboard1Id := 3
ITH1 := new InterceptionTapHold(AHI, keyboard1Id)
ITH1.Add("2", Func("Func"))
; Turn off InterceptionTapHold
ITH1.SetState(0)
ctrlHeld := 0
return

LCtrl::
   if (ctrlHeld)
      return ; Filter key repeat
   ctrlHeld := 1
   ITH.SetState(1) ; Turn on ITH while ctrl is held
   return

LCtrl up::
   ctrlHeld := 0
   ITH.SetState(0) ; Turn off ITH when CTRL is released
   return

Func(isHold, taps, state){
    ToolTip % "KB 1 Key 1`n" (isHold ? "HOLD" : "TAP") "`nTaps: " taps "`nState: " state
}
^Esc::
    ExitApp
evilC commented 6 days ago

Oh, if you want it the other way around, then simply swap the ITH.SetState() commands in the above example - ie set state to 0 on Ctrl down, and to 1 on Ctrl up. And delete the ITH.SetState(0) after the comment ; Turn off InterceptionTapHold

Momen-kh commented 5 days ago

Thanks a lot for helping me. I tried a lot but with no luck Holding ctrl with ( button 1 in my mouse ) also executes Func1. and the ctrl button remains held after I release it. Sorry for bothering with this.

Please if you could see my old working Code ( with morse pattern ): https://github.com/Momen-kh/AHK-Morse-Illustrator/blob/4bc8acbc66a2446c806d2594e1cd949ce6a6014e/MK__Illustrator_Morse.ahk

and here is the file I tried to do the same but with your helping in AutoHotInterception method: https://github.com/Momen-kh/AHK-Morse-Illustrator/blob/4bc8acbc66a2446c806d2594e1cd949ce6a6014e/AutoHotInterception_Test%20with%20Hotkeys.ahk

Thanks a lot for your time.

evilC commented 5 days ago

I don't have interception installed on my PC at the moment, so cannot really write tested code for AHI I cannot really test the non-AHI code you posted as I don't have illustrator What do you mean by "mouse 1"? It's ambiguous

Do you mean the left mouse button?

The 1st side button?

A programmable mouse button programmed to send keyboard key 1? The fact that in your script you have a hotkey to SC003 (The 2 key on the keyboard) which has comment Mouse button (2) leads me to believe that this is the case. Apart from in very special circumstances, AHI will not see SC003 that was sent by a mouse, because the mouse did not send it - software which came with your mouse did. A way to verify this is to run the AHI monitor, select one of the keyboards, and press that button on your mouse - does the monitor see it?

Also, it's worth noting that I will be away from this evening until Friday night, so you may not get a response from me for a while

I would also recommend that maybe you just code the logic you want with THM only for the moment, and forget about AHI. Once we have the logic nailed and I understand how it all works, then I could assist with converting it to use AHI