TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick buttons

Post your working scripts, libraries and tools for AHK v1.1 and older
jkwaza
Posts: 7
Joined: 13 Jan 2022, 11:23

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by jkwaza » 23 Feb 2022, 09:31

I have this keypad mapped and working perfectly with AHI, but cannot for the life of me get InterceptionTapHold work in any way.

Has anyone got the example scripts for InterceptionTapHold to work?

Just to clarify, I'm focussing on InterceptionTapHoldDemo.ahk which should show ToolTips when "1" or "2" key is pressed and should also block the keyboard1Id specified keypad like AHI does.

InterceptionTapHoldDemo.ahk doesn't throw any errors when I run it, so it's definitely okaying the PID and VID but not doing anything after that.

Why is it seeing the keypad USB ID but not blocking it nor assigning keys to it?


On the other hand the InterceptionSubscriptionModeExample.ahk continues to throw "Unknown mouse button name 1" and immediately closes.

Why does it only look for a mouse key and not a keyboard?

Any help or ideas on where it might be getting stuck would be greatly appreciated. Thanks.

jkwaza wrote:
19 Feb 2022, 11:02
Weeks of trying to solve this. Please help!

This is the Interception Mode Subscription Example.
Whenever I run it says: "Unknown mouse button name 1", the "1" is whatever key I add to kb1.

Also when I un-comment to get a list of devices, it shows a blank box, which is puzzling as I can get AutoHotInterception working very well.

Code: Select all

#include Lib\AutoHotInterception.ahk
#include Lib\TapHoldManager.ahk
#include Lib\InterceptionTapHold.ahk

#Persistent	; Interception scripts may not declare hotkeys, so you may need this to stop it exiting
#SingleInstance force

; Add the VID / PID of the keyboard you wish to filter here
VID1 := 0x04D9, PID1 := 0xA0F8

kb1 := new InterceptionTapHold(VID1, PID1)	; TapTime / Prefix can now be set here
kb1.Add("1", Func("Kb1Func"))			; TapFunc / HoldFunc now always one function

; Un-Comment this to get a list of devices
;devices := kb1.GetKeyboardList()
;Clipboard := devices
;msgbox % devices

Kb1Func(isHold, taps, state){
	ToolTip % "KB 1 Key 1`n" (isHold ? "HOLD" : "TAP") "`nTaps: " taps "`nState: " state
}

Kb2Func(isHold, taps, state){
	ToolTip % "KB 2 Key 1`n" (isHold ? "HOLD" : "TAP") "`nTaps: " taps "`nState: " state
}

I have also tried this too in Interception Tap Hold Demo, which doesn't subscribe/block keyboard nor assign a key.
I've come back to this so many times to give my external numpad TapHold functionality, but just having no luck. It looks like the clues are in TapHoldManager.ahk and InterceptionTapHold.ahk, but I cannot fully wrap my head around those.

Has anyone else experienced this?
What am I doing wrong?

Code: Select all

#SingleInstance force
#include <AutoHotInterception>
#include <InterceptionTapHold>
#include <TapHoldManager>

AHI := new AutoHotInterception()
keyboard1Id := AHI.GetKeyboardId(0x04D9, 0xA0F8) ;keypad
ITH1 := new InterceptionTapHold(AHI, keyboard1Id)
;ITH1 := new TapHoldManager()
ITH1.Add("1", Func("Func1"))
ITH1.Add("2", Func("Func2"))
return

Func1(isHold, taps, state){
    ToolTip % "KB 1 Key 1`n" (isHold ? "HOLD" : "TAP") "`nTaps: " taps "`nState: " state
}

Func2(isHold, taps, state){
    ToolTip % "KB 1 Key 2`n" (isHold ? "HOLD" : "TAP") "`nTaps: " taps "`nState: " state
}

jkwaza
Posts: 7
Joined: 13 Jan 2022, 11:23

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by jkwaza » 23 Feb 2022, 10:43

Okay, I'm an idiot. Because it's a numpad it doesn't send numbers.
It sends NumpadEnd for 1 and NumpadDn for 2, etc. Pretty sure I read that on the forum a while ago.

Also have gotten around the issue of it not blocking the keyboard by adding this line from AHI examples:

Code: Select all

AHI.SubscribeKeyboard(keyboard1Id, true, Func("KeyEvent"))
Thanks for reading!
Amazing how just articulating the problem and actually posting it on the forum is helping me solve these problems :morebeard:


BeerBread
Posts: 9
Joined: 09 Feb 2022, 22:22

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by BeerBread » 10 Mar 2022, 16:44

Hey guys! I'm back again! My scripts are running awesome from the last time and I really appreciated everyone's help! Now I'm at a point where I'm out of keys and I want to make use of the Shift, Alt, and Ctrl keys! I tried looking around the thread to see if there's a solution but no dice. Was this ever fixed or did anyone figure out how to bind them together?

Here's what I'm working on at the moment. I'm trying to do a hotkey where it kills the current script and switches to another. I'm also having trouble running my maintenance keys too not running. Toggling the SendMode Input portion of the header didn't yield any results:

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

#SingleInstance force
#Persistent
#include <AutoHotInterception> ; ! ! ! Without this external library AHI Scripts won't work.
#include <TapHoldManager> ; ! ! ! Without this external library THM Scripts won't work.
#include <InterceptionTapHold> ; ! ! ! Without this AHI Scripts won't work.
#include <XL> ;Allows Excel Functions
#IfWinActive ahk_class TscShellContainerClass()
#UseHook ;For Remote Desktop to work.

AHI := new AutoHotInterception() ; Initializing Interception
keyboardId := AHI.GetKeyboardId(0x1A2C, 0x4094) ; ; Retrieving the ID of the keyboard inside the Windows
ITH1 := new InterceptionTapHold(AHI, keyboardId) ; Initializing Interception Tap Hold (ITH)

ITH1.Add("^S", Func("CtrlSFunction"))

{
CtrlSFunction(isHold, taps, state)
	{
		If (isHold=0) & (taps=1) & (state) ;Opens other Script and Kills the Current One
		{
			run, "Script in Question" 
			Sleep, 1000
			Send, ExitApp
			return
		}
	}
}

^Esc::ExitApp	; Ctrl+Esc to terminate the script
^!p::Pause    ; Pause script with Ctrl+Alt+P
^!s::Suspend  ; Suspend script with Ctrl+Alt+S
^!r::Reload   ; Reload script with Ctrl+Alt+R

User avatar
SteveMylo
Posts: 233
Joined: 22 Jun 2021, 00:50
Location: Australia
Contact:

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by SteveMylo » 10 Mar 2022, 23:00

@BeerBread I'm no expert but and I only understand THM & not InterceptionTapHold.
But I believe you can't add two keys to THM. Ctrl and S have to be separate.

But there is a pause and resume hotkey in the manual in Github. I'll paste below.... It's like a (perfect) 'Keywait'.
I dont' know if it works in InterceptionTapHold but maybe you'll get something out of it.

Enabling or Disabling Hotkeys
Hotkeys can be disabled by calling PauseHotkey and passing the name of the key to pause:
thm.PauseHotkey("InsertKeyHere")

Hotkeys can be re-enabled by calling ResumeHotkey and passing the name of the key to resume:
thm.ResumeHotkey("InsertKeyHere")

Hotkeys can be removed by calling RemoveHotkey and passing the name of the key to remove:
thm.RemoveKey("InsertKeyHere")


e.g. Pressing "shift" will allow "space" to work

Code: Select all

#Include <TapHoldManager>
thm := new TapHoldManager()

thm.Add("Shift", Func("ShiftFunc"),,,1)    ;  important to add the ,,,1 at the end so it doesnt' wait for other taps and works instantly
thm.Add("Space", func("spaceFunc"),,,1)  ;  if you wanted to double tap 'space' then just change it to ,,,2  etc etc
thm.PauseHotkey("Space")  ; this sets "space' to 'pause' by default so it works as normal, but only is a hotkey if Shift is held 1st.  again, it's like the perfect Keywait which doesn't have any of the many cons of a normal Keywait. 


ShiftFunc(isHold, taps, state){
	    global thm
  if (isHold=1) & (taps=1) & (state=1){   ;  important to make it a 'HOLD' with the 'state=1' so it acts like your holding down shift.  
	 thm.ResumeHotkey("Space")
     return
}
}
                     
spaceFunc(isHold, taps, state){
    global thm    ; this line is needed for pause and resumes to work. 
    if (isHold=0) & (taps=1) & (state){
        
        thm.PauseHotkey("Space")
        SoundBeep
		return
    }
}                                                        

aacsel
Posts: 2
Joined: 03 Feb 2022, 17:52

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by aacsel » 27 Apr 2022, 21:47

Hi, I need help with this code.
I want to use LShift to press enter but if i hold LShift the key works normally

Code: Select all

thm := new TapHoldManager()	; TapTime / Prefix can now be set here
thm.Add("1", Func("MyFunc1"))			; TapFunc / HoldFunc now always one function
thm.Add("2", Func("MyFunc2"))

MyFunc1(isHold, taps, state){
  if (state){
    Send {LShift}
  }else if (state == -1){
    Send {Enter}
  }

}

User avatar
SteveMylo
Posts: 233
Joined: 22 Jun 2021, 00:50
Location: Australia
Contact:

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by SteveMylo » 27 Apr 2022, 22:16

@aacsel
Your hotkeys are 1 & 2. That’s incorrect. You need to change it to ‘LShift’.
Also, I use the newer method to write the code. and It works for me.

Code: Select all

#Include <TapHoldManager>
thm := new TapHoldManager()
thm.Add("LShift", Func("LShiftFunc"))

LShiftFunc(isHold, taps, state){
if (isHold=1) & (taps=1) & (state=1){    ;  state=1 means it activates when key is down.
    send, {LShift Down} 
    return
}

if (isHold=1) & (taps=1) & (state=0){     ;  state=0  means it activates when key is up.
   send, {LShift Up}  
   return
}

if (isHold=0) & (taps=1) & (state){
    send, {Enter}
    return
}
}
Last edited by SteveMylo on 28 Apr 2022, 15:22, edited 1 time in total.

User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by evilC » 28 Apr 2022, 11:04

aacsel wrote:
27 Apr 2022, 21:47
Hi, I need help with this code.
I want to use LShift to press enter but if i hold LShift the key works normally
Your code does not subscribe to LShift, it subscribes to 1 and 2
So of course LShift will continue to work as normal

hopeFalconer
Posts: 1
Joined: 05 May 2022, 10:40

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by hopeFalconer » 14 May 2022, 06:38

Greetings,

I have previously used single-tap-and-hold functionality with the following code and it did the job perfectly:

Code: Select all

SetCapsLockState, AlwaysOff

Capslock & h::Send {Blind}{Left Down}
Capslock & h up::Send {Blind}{Left Up}

Capslock & j::Send {Blind}{Down Down}
Capslock & j up::Send {Blind}{Down Up}

Capslock & k::Send {Blind}{Up Down}
Capslock & k up::Send {Blind}{Up Up}

Capslock & l::Send {Blind}{Right Down}
Capslock & l up::Send {Blind}{Right Up}

I have come across this TapAndHoldManager library when I am looking to implement double-tap-and-hold functionality.

I will try to explain the functionality I am trying to achieve:

tapping or holding j, sends j
I don't have any use for CapsLock so I will block it with SetCapsLockState, AlwaysOff
(single tap and holding Capslock) and (tapping or holding j), sends {Left}
(single tap and holding Capslock) and (tapping or holding j), sends {RIght} { I will change the functionality from Right to Volume Down later, just saying {Right} for simplicity }

I have tried to use this library to create barebones, but haven't achieved the functionality
The below code is my barebone version:

Code: Select all

#include Lib\TapHoldManager.ahk
#SingleInstance force
SetCapsLockState,AlwaysOff

thm := new TapHoldManager(,,2)
thm.Add("CapsLock", Func("MyFunc"))

jHoldManager := new TapHoldManager(,,1)



MyFunc(isHold, taps, state){
	global jHoldManager

	if ((isHold=1)&&(taps=1)&&(state=1)){
		jHoldManager.Add("j", Func("jFunc1"))
	}

	if (state=0){
		jHoldManager.RemoveHotkey("j")
	}

	if (isHold=1)&(taps=2)&(state=1){
		jHoldManager.Add("j", Func("jFunc2"))
	}
}


jFunc1(isHold, taps, state){
	/*
		while(state=1){
			Send, {Left}
		}
		
		if (state=-1){
			Send, {Left}
		}
	*/
	if (state=1){
		ToolTip, j jFunc1 state 1
	}
	if (state=0){
		ToolTip, j jFunc1 state 0
		Sleep, 500
		ToolTip
	}
	if (state=-1){
		ToolTip, j jFunc1 state -1
		Sleep, 500
		ToolTip
	}
}


jFunc2(isHold, taps, state){
	/*
		while(state=1){
			Send, {Right}
		}
		
		if (state=-1){
			Send, {Right}
		}
	*/
	if (state=1){
		ToolTip, j jFunc2 state 1
	}
	if (state=0){
		ToolTip, j jFunc2 state 0
		Sleep, 500
		ToolTip
	}

	if (state=-1){
		ToolTip, j jFunc2 state -1
		Sleep, 500
		ToolTip
	}
}
I am able to send single strokes to send the cursor to {Right} or {Left} easily (this part is also in the commented code to avoid confusion and only present working code to test)
I am unable to send continuous {Left} or {Right} if I hold j


I tried to implement the hold j functionality to send {Right} or {Left} using the while loop (commented out while code) to send Left or Right till the state becomes 0, but it just keeps on sending {Left} or {Right} even after I released the key and it only stops if I close the script.

I kindly request you to guide me in this small exercise

Jasonosaj
Posts: 46
Joined: 02 Feb 2022, 15:02
Location: California

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by Jasonosaj » 17 Jun 2022, 17:56

I'm trying to use taphold to invoke a menu with one click of !+S, and jump straight to a function with a double tap of the same hotkey (not sure if relevant, but that would translate to {altdown}{shiftsown}{s 2}{altup}{shiftup})

I've tried messing around with taptime, holdtime, and the parameters in each If statement. No matter what combination, I can't get it to consistently do what I want it to do. If there's anything glaringly obvious, here's the code:

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
; #Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
 menu, tray, icon, % a_scriptDir "\Media\Search.ico"
#SingleInstance,Force
;#NoTrayIcon
#Include lib\TapHoldManager.ahk
;------------------------------------------------------------------------------
; Automatically reload after edit, Part 1 
;------------------------------------------------------------------------------

FileGetTime ScriptStartModTime, %A_ScriptFullPath%
SetTimer CheckScriptUpdate, 200, 0x7FFFFFFF ; 200 ms, highest priority

;------------------------------------------------------------------------------
; Script
;------------------------------------------------------------------------------
/*
	tapTime The amount of time after a tap occured to wait for another tap. Defaults to 150ms.	
	holdTime The amount of time that you need to hold a button for it to be considered a hold. Defaults to the same as tapTime.
	maxTaps The maximum number of taps before the callback will be fired. Defaults to infinite.
	Setting this value to 1 will force the callback to be fired after every tap, whereas by default if you tapped 3 times quickly it would fire the callback once and pass it a taps value of 3, it would now be fired 3 times with a taps value of 1. If maxTaps is 1, then the tapTime setting will have no effect.
	prefix The prefix used for all hotkeys, default is $window An AHK WinTitle string that defines which windows the hotkey will take effect in For example, to make Hotkeys only work in Notepad, you could use:

*/

thm := new TapHoldManager(300,100) ; <tapTime := -1>, holdTime := -1, <maxTaps := -1>, <prefix := "$">, <window := "">

thm.Add("!+s", Func("SearchMenuHotkey"))

SearchMenuHotkey(isHold, taps, state){
	if (isHold=1) & (taps=1) & (state=1){    ;  state=1 means it activates when key is down.
		Menu, MyMenu, Add, 1 Search using DuckDuckGo, SearchDDGHandler
		Menu, MyMenu, Add, 2 Search using WolframAlpha, SearchWAHandler
		Menu, MyMenu, Add, 3 Translate using Google, GoogleTranslateHandler
		Menu, MyMenu, Add, 4 Correct grammar and spelling with Google, GoogleAutocorrectHandler
		Menu, MyMenu, Add, 5 WolframAlpha searchbox, WASearchBoxHandler
		Menu, MyMenu, Show
		Return
		}

	if (isHold=1) & (taps=2) & (state=0){     ;  state=0  means it activates when key is up.
	   DDGSearch()
	   return
		}
}
/*
!+S::
	Menu, MyMenu, Add, 1 Search using DuckDuckGo, SearchDDGHandler
	Menu, MyMenu, Add, 2 Search using WolframAlpha, SearchWAHandler
	Menu, MyMenu, Add, 3 Translate using Google, GoogleTranslateHandler
	Menu, MyMenu, Add, 4 Correct grammar and spelling with Google, GoogleAutocorrectHandler
	Menu, MyMenu, Add, 5 WolframAlpha searchbox, WASearchBoxHandler
	Menu, MyMenu, Show
	Return
*/

SearchDDGHandler:
	DDGSearch()
	Return
/*
	MyClip := ClipboardAll
	Clipboard = ; empty the clipboard
	Send, ^c
	ClipWait, 2
	if ErrorLevel { ; ClipWait timed out.
	    return
		}
	if RegExMatch(Clipboard, "^(https?://|www\.)[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$") {
	    Run % Clipboard
	    }
	else {
	    ; Modify some characters that screw up the URL
	    ; RFC 3986 section 2.2 Reserved Characters (January 2005):  !*'();:@&=+$,/?#[]
	    StringReplace, Clipboard, Clipboard, `r`n, %A_Space%, All
	    StringReplace, Clipboard, Clipboard, #, `%23, All
	    StringReplace, Clipboard, Clipboard, &, `%26, All
	    StringReplace, Clipboard, Clipboard, +, `%2b, All
	    StringReplace, Clipboard, Clipboard, ", `%22, All
	    Run % "https://duckduckgo.com/?q=" . clipboard ; uriEncode(clipboard)
	}
	Clipboard := MyClip
	return
*/

SearchWAHandler:
	WAsearch()
	Return
	
GoogleTranslateHandler:
	GoogleTranslate()
	Return

GoogleAutocorrectHandler:
	clipback := ClipboardAll
	clipboard=
	Send ^c
	ClipWait, 0
	UrlDownloadToFile % "https://www.google.com/search?q=" . clipboard, temp
	FileRead, contents, temp
	FileDelete temp

	if (RegExMatch(contents, "(Including results for|Showing results for|Did you mean:)(.*?)</a>", match)) {
		match2 := RegExReplace(match2,"<.+?>")
		StringReplace, match2, match2, &#39;,', All
	}
	; msgbox %match2%
	SendInput %match2%
	Sleep 500
	clipboard := clipback
	Return

WASearchBoxHandler:
	Inputbox, WAQuery, Wolfram|Alpha search string
	If ErrorLevel {
		MsgBox, Search cancelled
		Return
		}
	Else {
		If RegExMatch(WAQuery, "^(https?://|www\.)[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$") {
			Run % WAQuery
			Return
			}
		Else {
			StringReplace, WAQuery, WAQuery, `r`n, %A_Space%, All
			StringReplace, WAQuery, WAQuery, #, `%23, All
			StringReplace, WAQuery, WAQuery, &, `%26, All
			StringReplace, WAQuery, WAQuery, +, `%2b, All
			StringReplace, WAQuery, WAQuery, ", `%22, All
			Run % "https://www.wolframalpha.com/input?i=" . WAQuery
			Return
			}
		}
	Return	


DDGSearch() {
	MyClip := ClipboardAll
	Clipboard = ; empty the clipboard
	Send, ^c
	ClipWait, 2
	if ErrorLevel { ; ClipWait timed out.
	    return
		}
	if RegExMatch(Clipboard, "^(https?://|www\.)[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$") {
	    Run % Clipboard
	    }
	else {
	    ; Modify some characters that screw up the URL
	    ; RFC 3986 section 2.2 Reserved Characters (January 2005):  !*'();:@&=+$,/?#[]
	    StringReplace, Clipboard, Clipboard, `r`n, %A_Space%, All
	    StringReplace, Clipboard, Clipboard, #, `%23, All
	    StringReplace, Clipboard, Clipboard, &, `%26, All
	    StringReplace, Clipboard, Clipboard, +, `%2b, All
	    StringReplace, Clipboard, Clipboard, ", `%22, All
	    Run % "https://duckduckgo.com/?q=" . clipboard ; uriEncode(clipboard)
	}
	Clipboard := MyClip
}

WAsearch() {
	MyClip := ClipboardAll
	Clipboard := ; empty the clipboard
	Send, ^c
	ClipWait, 2
	if ErrorLevel  { ; ClipWait timed out.
	    return
	    }
	if RegExMatch(Clipboard, "^(https?://|www\.)[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?$") 
	{
		Run % Clipboard
		}
	else { ;*[Search - SHIFT ALT S or T - Google Search & Translate]
	    ; Modify some characters that screw up the URL
	    ; RFC 3986 section 2.2 Reserved Characters (January 2005):  !*'();:@&=+$,/?#[]
	    StringReplace, Clipboard, Clipboard, `r`n, %A_Space%, All
	    StringReplace, Clipboard, Clipboard, #, `%23, All
	    StringReplace, Clipboard, Clipboard, &, `%26, All
	    StringReplace, Clipboard, Clipboard, +, `%2b, All
	    StringReplace, Clipboard, Clipboard, ", `%22, All
	    Run % "https://www.wolframalpha.com/input?i=" . clipboard ; uriEncode(clipboard)
	}
	Clipboard := MyClip
	return
}

GoogleTranslate() {
	MyClip := ClipboardAll
	Clipboard = ; empty the clipboard
	Send, ^c
	ClipWait, 2
	if ErrorLevel { ; ClipWait timed out.
	    return 
		}
	StringReplace, Clipboard, Clipboard, `%, `%25, All ; has to come first
	StringReplace, Clipboard, Clipboard, `r`n, `%0A, All
	Run % "https://translate.google.com/#auto|en|" . clipboard ; uriEncode(clipboard)
	Clipboard := MyClip
	return	
}
;------------------------------------------------------------------------------
; Automatically reload after edit, Part 2 
;------------------------------------------------------------------------------

CheckScriptUpdate() {
	global ScriptStartModTime
	FileGetTime curModTime, %A_ScriptFullPath%
	If (curModTime <> ScriptStartModTime) {
		SetTimer CheckScriptUpdate, Off
		Loop
		{
			reload
			Sleep 300 ; ms
			MsgBox 0x2, %A_ScriptName%, Reload failed. ; 0x2 = Abort/Retry/Ignore
			IfMsgBox Abort
				ExitApp
			IfMsgBox Ignore
				break
		} ; loops reload on "Retry"
	}
}

User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by evilC » 17 Jun 2022, 19:02

@Jasonosaj if (isHold=1) & (taps=2) & (state=0){ will activate on the release of a double tap and hold.
ie hold shift + alt, press s, quickly release s, press s, WAIT, release s, release shift + alt
ie a tap of S and then a hold of S, whilst holding shift + alt

This triggers perfectly reliably for me, I used key down for the double-tap-and-hold, not really sure why you need to use key down for one and up for the other, so I just used key down for both :

Code: Select all

#Include lib\TapHoldManager.ahk

thm := new TapHoldManager() ; <tapTime := -1>, holdTime := -1, <maxTaps := -1>, <prefix := "$">, <window := "">
thm.Add("!+s", Func("SearchMenuHotkey"))
SearchMenuHotkey(isHold, taps, state){
    if (isHold && state){
        if (taps==1){
            MSGBOX Menu
        } else if (taps==2){
            MSGBOX DDGSearch
        }
    }
}

Jasonosaj
Posts: 46
Joined: 02 Feb 2022, 15:02
Location: California

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by Jasonosaj » 17 Jun 2022, 19:12

I swear to God, this community is THE BEST. Thanks so much, Evil. I'll fix the script and confirm that it works once I get home.

Jasonosaj
Posts: 46
Joined: 02 Feb 2022, 15:02
Location: California

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by Jasonosaj » 21 Jun 2022, 09:51

@evilC I ended up messing around a bit and limting the IFs to (taps == X) speeds up the script considerably. Otherwise, thanks for the Library and the guidance!

User avatar
SteveMylo
Posts: 233
Joined: 22 Jun 2021, 00:50
Location: Australia
Contact:

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by SteveMylo » 21 Jun 2022, 16:50

@evilC hey there. Is there a way to create an .ini file to change the hotkey after it’s become an .exe file? You know, if I intended to sell a script if the hotkeys incorporated THM?
Possible or impossible?

User avatar
evilC
Posts: 4822
Joined: 27 Feb 2014, 12:30

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by evilC » 22 Jun 2022, 03:41

Yes, it's totally possible - at the end of the day, which hotkey is used is ultimately goverened by a call such as thm.Add("1", Func("MyFunc1")) - so in this example, you just need to read a value from the ini file into a variable and instead call thm.Add(valueFromIniFile, Func("MyFunc1"))
Being able to reassign the key from within the app, however (As opposed to just editing the INI file manually prior to launching the script) is another matter entirely - I have an example of how to do this (Albeit with regular hotkeys) here: https://github.com/evilC/AppFactory

User avatar
SteveMylo
Posts: 233
Joined: 22 Jun 2021, 00:50
Location: Australia
Contact:

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by SteveMylo » 22 Jun 2022, 07:58

@evilC amazing thankyou. I'll be paying someone in the future to do it for me.
Can I ask, do you do paid work if on offer? full rates?. To add things like this to codes?
I prefer someone in Australia close by to sit with but you are very well known so I can trust you cause I've seen tonnes of your work.
Not anytime soon, just later this year. if not all good I'll keep looking.
Cheers mate


User avatar
SteveMylo
Posts: 233
Joined: 22 Jun 2021, 00:50
Location: Australia
Contact:

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by SteveMylo » 22 Jun 2022, 15:45

No drama. Appreciate all your hard work with this clever script.

Jasonosaj
Posts: 46
Joined: 02 Feb 2022, 15:02
Location: California

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by Jasonosaj » 18 Aug 2022, 12:36

GOAL: use capslock to (1) invoke a menu that accesses various scripts/functions upon double tap (tap==2) of CAPSLOCK; (2) quick jump to various folders/scripts/functions upon hold (isHold) of CAPSLOCK and simultaneous/subsequent [LETTER KEY] (e.g., caps + d --> C:\Downloads; caps + o --> OCR script; etc.).

CODE [excerpt from much larger script]:

Code: Select all

	; INITIALIZATION
	; ...
	
	thm := new TapHoldManager(,,, "$")
	thm.Add("Capslock", Func("CapsHotkeyFunc"))
	Return
	
	; ... [
	
	capsHotkeyFunc(isHold, taps, state) {
		If (!state) {
			return
			}
		If (isHold) {
			If Getkeystate("D","P") {
				if WinExist("ahk_class dopus.lister") {
					WinActivate
					Run, G:\Downloads
					}
				else {
					Run, G:\Downloads
					}
				}
			Else if (Getkeystate("w") == 1) {
				if WinExist("ahk_class dopus.lister") {
					WinActivate
					Run, C:\Users\jason\OneDrive - Work\8 - Work Downloads
					}
				else {
					Run, C:\Users\jason\OneDrive - Work\8 - Work Downloads
					}
				}
			Else if (Getkeystate("c") == 1) {
				if WinExist("ahk_class dopus.lister") {
					WinActivate
					Run, C:\Users\jason\OneDrive - Work\1 - Cases
					}
				else {
					Run, C:\Users\jason\OneDrive - Work\1 - Cases
					}
			}
			Else if (Getkeystate("s") == 1) {
				if WinExist("ahk_class dopus.lister") {
					WinActivate
					Run, C:\Users\jason\OneDrive\5 - SCRIPTING\AHK\
					}
				else {
					Run, C:\Users\jason\OneDrive\5 - SCRIPTING\AHK\
					}
				}
			}
		Else If (taps == 2) {
			QuickClip(0.5)
			F1HotkeyFunction(Stringtemp)
			}
		Return
		
		; ...
PROBLEM: The double-tap function works, no issues there. The isHold functions work IF the letter key is depressed at the time the capslock is registered as held; they don't work if I press the letter key at the same time as or subsequent to holding down the capslock. Anyone know what I'm doing wrong???

Epoch
Posts: 41
Joined: 04 Jun 2021, 11:09

Re: TapHoldManager - Long Press / Multi Tap / Multi Tap and Hold / Any number of Taps / Multi-Keyboard / Joystick button

Post by Epoch » 28 Aug 2022, 11:48

Congratulations on this great script. I've been trying without success to achieve two things:
1. Having a context sensitive TapHoldManager instance, for example having its hotkey taking effect only on windows explorer. Simply starting with #if Winactive, as in the following example doesn't seem to work.

Code: Select all

#If WinActive("ahk_exe explorer.exe")

thm := new TapHoldManager(150, 300, , "$*") ; 
thm.Add("a", Func("DefaultFunction"))

DefaultFunction(isHold, taps, state){
	if (!state)
		return ; Only take action on key press, not key release (prevents sending actions twice)
	if (isHold){
		; Holds
		if (taps == 1){
			msgbox You have tapped and  held "a".
		} else if (taps == 2){
			msgbox You have tapped "a" 2 times and held the second tap.
		}
	} else {
		; Taps
		if (taps == 1){
			msgbox You have tapped "a" 1 time.
		} else if (taps == 2){
			msgbox You have tapped "a" 2 times.
		}
	}
}
return

#If WinActive
2. Using a key combination containing an F key as my tapholdmanager hotkey. I've set a mouse button as "F13", allowing me to combine it with various keyboard keys for different actions i.e

Code: Select all

F13 & H:: Do this
So I'd like to hold F13 (the mouse button) while tapping, double tapping, holding etc. the H key in order to get different actions (but only when Windows explorer is active as I've already said). Is this possible?

Thanks a lot.

Post Reply

Return to “Scripts and Functions (v1)”