Jump to content


Photo

Toggle (Hold Down) a Key


  • Please log in to reply
7 replies to this topic

#1 mario1776

mario1776
  • Members
  • 13 posts

Posted 08 April 2012 - 12:17 PM

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}


#2 nimda

nimda
  • Members
  • 4301 posts

Posted 08 April 2012 - 10:58 PM

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)

#3 Guests

  • Guests

Posted 09 April 2012 - 12:00 AM

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}


#4 nimda

nimda
  • Members
  • 4301 posts

Posted 09 April 2012 - 12:04 AM

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.

#5 mario1776

mario1776
  • Members
  • 13 posts

Posted 09 April 2012 - 12:13 AM

$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.

#6 nimda

nimda
  • Members
  • 4301 posts

Posted 09 April 2012 - 01:39 AM

You're missing
#MaxThreadsPerHotkey 2
in your code.

#7 puffdragon

puffdragon
  • Members
  • 1 posts

Posted 06 February 2013 - 01:36 PM

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...



#8 JadeDragon

JadeDragon
  • Members
  • 587 posts

Posted 06 February 2013 - 02:05 PM

#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.