I have an ahk script which types a series of keys. It works up until the last key. When it comes to the last key, the AHK script just seems to hold down the key until I press another key manually or exit the script (which I don't want to do).
#SingleInstance force
Sleep, 3000
Send {r}
Sleep, 100
Send {u}
Sleep, 100
Send {n}
Sleep, 100
Exit
I mean, its a straight forward script but instead of seeing "run" I get "runnnnnnnnnnnnnnn(... to infinity)". It should be noted that if I make the sleep command longer, each key will be held down for that amount of time. 100 seconds ensures I only get the character once (except the last key) before moving on to the next.
How can I guarantee that the script will only press each key once?
I see nothing wrong with your use of the method, but your keyboard, lag/latency, and the specific program you're sending keys to can effect the reliability of the Send method. Clearly, your keyboard is not releasing the key at all, since you have to trim the Sleep to 100ms to ensure a single press. I use this custom KeyPress() method to help ensure keypresses in finicky programs. It sends the "press" and "release" portions of the keypress on different ticks. Sleeping by 1 ms ensures at least 1 tick will pass between commands.
Note that for this to work, you must pass a literal string to the Keypress() method. Hence, you must send the key you wish to press enclosed in double quotation marks
#SingleInstance force
F10::
{
KeyPress("r")
KeyPress("u")
KeyPress("n")
}
KeyPress(Key)
{
Send, {%Key% down}
Sleep 1
Send, {%Key% up}
Sleep 1
}
Responding to the comment stating that the X of the XY Problem is that OP wants a script that will Delay 3 seconds before sending "run".
#SingleInstance force
Sleep, 3000
SendInput run ;SendInput is more reliable than Send when trying to send plaintext to programs
Related
I'm trying to send the output of my code to an inactive application using Auto Hotkey on my computer so I don't have to be on the screen and can do other stuff. How would I go about implementing it?
F1::
stop := 0
Loop
{
Send, z
Sleep 500
}until Stop
return
F2::Stop := 1
This is the code I have down so far, any help?
ControlSending might work. It's basically a hit or miss. It'll work for some applications, and for some it wont.
It'll be worth a try for you though.
Also, you're going to want to use a timer as opposed to looping in a hotkey thread. Timer is intended just for something like this and what you were doing is kind of bad practice for various reasons.
;timer runs the user-defined function "SendZ" every 500ms
F1::SetTimer, SendZ, 500
F2::SetTimer, SendZ, Off
SendZ()
{
ControlSend, , z, % "ahk_exe notepad.exe"
}
As a bonus, we can even write a sweet one liner to toggle on/off that timer by using a ternary:
F1::SetTimer, SendZ, % (Toggle:=!Toggle) ? 500 : "Off"
If that doesn't make sense to you, and you're interested, you can read a lengthy previous explanation of mine about it here.
My idea was to a command like "Sleep, 2000" in a variable or even several commands.
In this example you would type in the hotstring, then the program would wait 2 seconds and then the message box would pop up and tell you that you've slept for 2 seconds.
However, I'm getting an error message for the line with "SleepVar1": "This line doesn't contain a recognized action"
SleepVar1 = Sleep, 2000
:*:svar::
SleepVar1
msgbox, You slept 2 seconds
return
There must be a way to achieve this, right? Maybe not with variable but something else.
As the names suggest:
Commands are orders, tasks given to the OS.
A variable is a placeholder for a value. The value can change, nevertheless a variable can only hold one value at a time.
To return a given value of a variable within commands, you need to enclose the variable in
percent signs
SleepVar1 = 2000
:*:svar1::
Sleep, %SleepVar1%
msgbox, You slept 2 seconds
return
or a function:
; :X*:svar2::SleepVar(3000)
; or
:*:svar2::
SleepVar(3000)
return
SleepVar(value){
Sleep, %value%
msgbox, You slept %value% miliseconds
}
The title has it. Shift is too far away to reach for making a letter capital; want to use these two ALTs instead. Here is one of my numerous attempts:
If GetKeyState("LAlt") & GetKeyState("RAlt")
send {Shift Down}
else
send {Shift Up}
Please do read https://autohotkey.com/docs/Hotkeys.htm, specially the beginning. Hotkeys start with a :: and end with a return.
In your case, you are looking for a remapping: Please look into https://autohotkey.com/docs/misc/Remap.htm.
For guidance, but not tested:
You could probably do something like
<!>!Alt::Shift
I'm new to psychopy and python. I'm trying to program a way to quit a script (that I didn't write), by pressing a key for example. I've added this to the while loop:
while n < total
start=time.clock()
if len(event.getKeys()) > 0:
break
# Another while loop here that ends when time is past a certain duration after 'start'.
And it's not working, it doesn't register any key presses. So I'm guessing key presses are only registered during specific times. What are those times? What is required to register key presses? That loop is extremely fast, sending signals every few milliseconds, so I can't just add wait commands in the loop.
If I could just have a parallel thread checking for a key press that would be good too, but that sounds complicated to learn.
Thanks!
Edits: The code runs as expected otherwise (in particular no errors). "core" and "event" are included. There aren't any other "event" command of any kind that would affect the "key press log".
Changing the rest of the loop content to something that includes core.wait statements makes it work. So for anybody else having this difficulty, my original guess was correct: key presses are not registered during busy times (i.e. in my case a while statement that constantly checks the time), or possibly only during specific busy times... Perhaps someone with more knowledge can clarify.
....So I'm guessing key presses are only registered during specific
times. What are those times? What is required to register key
presses?....
To try and answer your specific question, the psychopy api functions/methods that cause keyboard events to be registered are ( now updated to be literally every psychopy 1.81 API function to do this):
event.waitKeys()[1]
event.clearEvents()[1]
event.getKeys()[2]
event.Mouse.getPressed()
win.flip()
core.wait()
visual.Window.dispatchAllWindowEvents()
1: These functions also remove all existing keyboard events from the event list. This means that any future call to a function like getKeys() will only return a keyboard event if it occurred after the last time one of these functions was called.
2: If keyList=None, does the same as *, else removes keys from the key event list that are within the keyList kwarg.
Note that one of the times keyboard events are 'dispatched' is in the event.getKeys() call itself. By default, this function also removes any existing key events.
So, without being seeing the full source of the inner loop that you mention, it seems highly likely that the event.getKeys() is never returning a key event because key events are being consumed by some other call within the inner loop. So the chance that an event is in the key list when the outer getKeys() is called is very very low.
Update in response to OP's comment on Jonas' test script ( I do not have enough rep to add comments to answers yet):
... Strange that you say this ..[jonas example code].. works
and from Sol's answer it would seem it shouldn't. – zorgkang
Perhaps my answer is giving the wrong understanding, as it is intended to provide information that shows exactly why Jonas' example should, and does, work. Jonas' example code works because the only time key events are being removed from the event buffer is when getKeys() is called, and any events that are removed are also returned by the function, causing the loop to break.
This is not really an answer. Here's an attempt to minimally reproduce the error. If the window closes on keypress, it's a success. It works for me, so I failed to reproduce it. Does it work for you?
from psychopy import event, visual, core
win = visual.Window()
clock = core.Clock()
while True:
clock.reset()
if event.getKeys():
break
while clock.getTime() < 1:
pass
I don't have the time module installed, so I used psychopy.core.Clock() instead but it shouldn't make a difference, unless your time-code ends up in an infinite loop, thus only running event.getKeys() once after a few microseconds.
I have an AutoHotkey script in which the left-mouse-button is mapped to a function. Part of the function includes simulating a left-button click offset from the actual cursor position. Not surprisingly, this ends up becoming a bit of an infinite loop.
Likewise, there is a handler that traps a key-press and performs some math before passing the key-press on through.
Is there a way perform a click without triggering the click-handler? Similarly, is there a way to send a key-press without triggering the key-press-handler?
Trap() {
MouseGetPos, x,y
;Perform some math with x and y
Click %x% %y% left ;oops, this causes Trap to get called again
}
LButton:: Trap
From the AutoHotkey manual:
$ - This is usually only necessary if the script uses the Send command to send the keys that comprise the hotkey itself, which might otherwise cause it to trigger itself.
That does the trick:
$LButton:: Trap
I actually do not see the looping behaviour you describe, so I wonder if there is some other factor at play.
If that really is the problem, then you can use a boolean flag to prevent recursive execution:
isTrapping := false
Trap() {
global isTrapping
if isTrapping = true
return
isTrapping := true
MouseGetPos x, y
; do some maths with x & y
Click %x%, %y%
isTrapping := false
}
LButton::Trap()