Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Toggle (Hold Down) a Key


  • Please log in to reply
7 replies to this topic
mario1776
  • Members
  • 18 posts
  • Last active: Nov 08 2015 08:45 PM
  • Joined: 27 Feb 2011
I would like to be able to press a key on the keyboard once and have an autohotkey script hold that key down, until the keyboard key is pressed again to release it. I have tried several different ways of accomplishing this but so far at best I can only get the particular key to be pressed once and then it stops, attempts to Send {WhateverKeyboardKey Down} have failed to actually hold down and continually send the particular keys; additionally I'm concerned succeeding in getting the script to hold down a key may dump the script into an uncontrollable loop and perhaps make it ignore the follow up key press intended to toggle off the particular key which is why one of my attempts tried using WASD and IJKL to toggle Up, Down, Left, Right. Any help would be appreciated. All of my attempts use specifically identified keys, but I imagine there would be a way to use %A_ThisHotKey% to make the toggling script generic so that it would work for any key pressed on the keyboard.

;n::ToolTip % (t := !t) ? "Bla" : "Ble"
;Down::
;if t := !t ? Send {Down Down} : Send {Down Up}

n=0   ; this isn't really needed, the invert of empty is 1
return
s::
n:=!n         ; invert or reverse the prior value, 1 or 0 are the only choices
if n=1
  Send {Down down} tooltip, thi i down
else
  Send {Down up} tooltip, thi i up
return
SetBatchLines -1
#UseHook
Increment = 1 ; number of pixels to move mouse....gets multiplied depending on keypress length

MouseDelay = 0

w::
a::
s::
d::
xVal=
yVal=
If GetKeyState("CapsLock","T")
   {
      IncrementValue := Increment ; Set the Increment value (we change it)
      ; Infinite loop....breaks when key not pressed anymore
      Loop,
      {
      ;If (A_Index > IncrementValue * 15) and (IncrementValue < Increment * 5) ; Increase the Increment value depending on how long we held down the key
         ;IncrementValue := IncrementValue * 2

      If GetKeyState("s", "P")
Send {Down down}
      Else If GetKeyState("w", "P")
Send {Up down}

      If !yVal
         yVal := 0

      If GetKeyState("a", "P")
Send {Left down}
      Else If GetKeyState("d", "P")
Send {Right down}

      If !xVal
         xVal := 0

         MouseMove, %xVal%, %yVal%,%MouseDelay%,R
         KeyWait, %A_ThisHotKey%
         Break
      }
   }
Else
   Send % "{" . A_ThisHotKey . "}"
return

Esc::ExitApp
a::
Send {Left down}  ; Hold down the left-arrow key.
return

j::
Send {Left up}  ; Release the left-arrow key.
return

d::
Send {Right down}  ; Hold down the Right-arrow key.
return

l::
Send {Right up}  ; Release the Right-arrow key.
return

w::
Send {Up down}  ; Hold down the Up-arrow key.
return

i::
Send {Up up}  ; Release the Up-arrow key.
return

s::
Send {Down down}  ; Hold down the Down-arrow key.
return

k::
Send {Down up}  ; Release the Down-arrow key.
return
a:: ;These two likes also
If GetKeyState("CapsLock","p")
 Send {Left Down} ;press down the Left key
else
 Send a
Return
a Up::Send {Left Up}


nimda
  • Members
  • 4368 posts
  • Last active: Aug 09 2015 02:36 AM
  • Joined: 26 Dec 2010
I would do it like this:
#MaxThreadsPerHotkey 2
k::
t := !t
while t
    Send {k down}
For more info, see the autofire link in my signature. (note that some of the code is wrapped in [color] tags which need to be removed)

  • Guests
  • Last active:
  • Joined: --

I would do it like this:

#MaxThreadsPerHotkey 2

m::

t := !t

while t

    Send {m down}
On the downside nimda's method seems to fail at correctly executing a key that has been pressed. When tried with the letter "m" you can open AHK and see that m down is being sent over and over, yet when exectued with a notepad open it does not produce "mmmmmmmmmmmmmmmmm" as would be expected. On the upside nimda's method does succeed (sorta) when mapping to other keys as shown below. You can hit the key s and it will correctly execute {down down}, but as I feared, it becomes an uncontrollable loop that you have to reload the script to break, pressing the key a second time to toggle it does not work with this code.
#MaxThreadsPerHotkey 2

w::

t := !t

while t

    Send {Up down}

s::

t := !t

while t

    Send {Down down}

a::

t := !t

while t

    Send {Left down}

d::

t := !t

while t

    Send {Right down}


nimda
  • Members
  • 4368 posts
  • Last active: Aug 09 2015 02:36 AM
  • Joined: 26 Dec 2010
I was missing a line at the end of the hotkey:
Send {m up}
As well, the hotkey definition should have been:
$m::
The dollar-sign prevents infinite loops.

It's problems like this which made me compile lots of working code into one thread... we'll just need to wait for color tags inside code tags to work again.

mario1776
  • Members
  • 18 posts
  • Last active: Nov 08 2015 08:45 PM
  • Joined: 27 Feb 2011
$w::
t := !t
while t
{
Send {Up down}
}
Send {Up up}
Have tried making appro changes but still does not succeed in stopping the runaway loop.

P.S. Any advice on getting to work with logical key presses would also be greatly appreciated. Will not work when tested through vnc.

nimda
  • Members
  • 4368 posts
  • Last active: Aug 09 2015 02:36 AM
  • Joined: 26 Dec 2010
You're missing
#MaxThreadsPerHotkey 2
in your code.

puffdragon
  • Members
  • 1 posts
  • Last active: Feb 06 2013 01:40 PM
  • Joined: 06 Feb 2013

I"m trying to do the same thing as the OP.

 

Need to press a key once, and this key to be hold down till i press that key again. Methods posted here aren't working so far or I missed something...



JadeDragon
  • Members
  • 935 posts
  • Last active: Jun 07 2014 07:40 AM
  • Joined: 18 Jan 2013
#MaxThreadsPerHotkey, 2
looping = 0

$m:: ;<-- the hotkey with a $ so it won't re-trigger itself

tooltip, Release the "m" key to continue ;<-- a reminder to let go of the "m"
keywait, m ;<-- make sure to let go of the m key
tooltip ;<-- turn off the reminder

looping := !looping ;<-- is the switch to tell the loop to start or stop
if (!looping)  ;<-- if the toggle is now off don't do the loop
   Return
loop ;<-- an infinite loop with a break condition inside
{   If (!looping) ;<-- the loop will break once the looping flag is flipped off
        Break
    Tooltip, looping is %looping%
    send, {m down}
    ;send {k down}
    sleep, 200
}
Send, {m up}
; send {k up}
Tooltip
ExitApp


One important thing to remember is that in Notepad the keys all repeat anyway so really the only way to effectively test a loop like this with Notepad is to send a different key than the one used for the definition or to make sure the key is released before sending to Notepad. Also this, in no way, is intended to supercede nimda's code. There is a fine thread on autofire routines here on the forums. I tend to be much more conservative when writing autofire loops like this because of the potential for retriggering and keys being sent too fast that's why the keywait and the sleep in the loop and why the #MaxThreadsPerHotkey is set only to 2 and why I force the looping variable to 1 at the beginning. I left the different send (the k down and up) lines in so you can test with Notepad by simply un-commenting those lines and commenting out the m sends.


Never assume evil intent when simple ignorance will suffice. Ignorance is an eventually curable condition with the right education. Evil intent, however, is another matter entirely. Scripts are much like children. Simple to conceive. Difficult, expensive, and time-consuming to raise. Often do the opposite of what you expect them to. Require frequent  "correction". And once they leave home you can't control them anymore. But you love them anyway.