Autohotkey:每当我释放按钮时,都会在特定点过早结束长循环。 (如果不寻找循环以外的其他命令)
Autohotkey: Ending a long loop at specific point prematurely whenever I release a button. (if not looking for other command than loop)
问题
你好,我是一般编码的新手,想知道我是否可以过早地结束 autohotkey 中的循环功能。例如在下面的代码中,如果我按下按钮 x 并释放它,它会以一秒的间隔键入 b、s、c、y 和 u。我想要的是,如果我按下 x 一秒钟然后释放 x,它会发送 b 然后终止循环。如果我按 x 两秒钟,它会发送 b 和 s 然后终止,等等。现在的问题是无论我点击 x一两秒等,它完成循环,发送 b、s、c、y 和 u。
*$x::
While(GetKeyState("x", "P"))
{
send b
Sleep 1000
send s
Sleep 1000
send c
Sleep 1000
send y
Sleep 1000
send u
Sleep 1000
}
Return
寻找解决方案
因为我对 autohotkey 和一般编码不熟悉,所以我能想到的就是使用循环,但我认为在这种情况下使用是错误的。我正在寻找解决方案,上面的代码不必是循环(重复)。我想要的只是如果我按下按钮 x 一定秒数,它会相应地发送上面的字母。感谢您阅读这篇相当长的文章 post。
我可以看到一些可能的方法。
1) 第一个也是最糟糕的是在每次发送后有一个 if... 来测试键状态和退出。这是非常重复的,但如果你把它放在一个函数中并只是调用它就不会太糟糕,比如:
*$x::
while (GetKeyState("x", "P")) {
sendStuff('b')
sendStuff('s')
sendStuff('c')
...
}
sendStuff(str) {
Send str
if (!GetKeyState("x", "P")) {
exit
}
sleep 1000
}
2) 接下来是继续按原样操作,使用一系列链接命令,并有一个外部的、单独的脚本在 运行 时终止该系列命令,然后重新 Run()
你的脚本,当你想重新启动。常见问题解答中介绍了杀死外部脚本,此处:http://www.autohotkey.com/docs/FAQ.htm#close
那里有三个相关部分,粘贴在这里有点长,但总而言之,您可能对以下命令感兴趣:
; Allow script's hidden main window to be detected.
DetectHiddenWindows On
; Avoid need to specify full path of file.
SetTitleMatchMode 2
; Kill another script: Update params to the script's case sensitive name.
WinClose Script Filemame.ahk - AutoHotkey
; Suspend other script.
PostMessage, 0x111, 65305,,, Script Filename.ahk - AutoHotkey
; Pause other script.
PostMessage, 0x111, 65306,,, Script Filename.ahk - AutoHotkey
; Pause/resume current script on Ctrl+Alt+P
^!p::Pause
3) 下面还有一个更长的代码示例,它描述了取消循环,我相信这是解决这个问题的正确方法,因为虽然它最初可能比较繁琐,但它的可扩展性要高得多,减少代码重复,并允许您在一个地方处理多个循环 entry/exit 条件。
简而言之,就编程风格而言,它是最好的。
将您希望发送的条目 (b, s, c, y, u) 放入字符串、数组或其他可迭代数据结构中,并对其进行迭代,以便您的 while 循环仅发送一个项目并且每次迭代暂停一次。然后,下次您按下热键时,您可以从中断的地方继续循环,也可以重新开始,具体取决于您是否保留指向结构中当前位置的指针。
例如,使用上面的 sendStuff 函数,循环将为您提供非常强大且易于扩展的功能:
*$x::
{
letters = b,s,c,y,u
Loop, parse, letters, `,
sendStuff(%A_LoopField%)
return
}
x::
index:="i"
letters:="l"
output:="o"
l:="bscyu"
i:=(i<o0?++i:1)
StringSplit,o,l
send % o%i%
sleep,1000
return
x Up::i:=0
这个post这么老了,就是忍不住
sendChars := "bscyu"
$x::
i := 1 ; (!i ? 1 : i) ; permits starting where left off.
While (getKeyState("x", "P")) {
Send % subStr(sendChars, i, 1)
i := ((i==strLen(sendChars)) ? 1 : (i+1))
if (getKeyState("x", "P")) { ; why wait if you don't have to.
Sleep 1000
}
}
文档指出 While 循环仅在每次迭代开始时进行评估,因此在循环中列出所有键只会发送所有键,然后再次在顶部跳出循环并查看不再按下“x”。
问题
你好,我是一般编码的新手,想知道我是否可以过早地结束 autohotkey 中的循环功能。例如在下面的代码中,如果我按下按钮 x 并释放它,它会以一秒的间隔键入 b、s、c、y 和 u。我想要的是,如果我按下 x 一秒钟然后释放 x,它会发送 b 然后终止循环。如果我按 x 两秒钟,它会发送 b 和 s 然后终止,等等。现在的问题是无论我点击 x一两秒等,它完成循环,发送 b、s、c、y 和 u。
*$x::
While(GetKeyState("x", "P"))
{
send b
Sleep 1000
send s
Sleep 1000
send c
Sleep 1000
send y
Sleep 1000
send u
Sleep 1000
}
Return
寻找解决方案
因为我对 autohotkey 和一般编码不熟悉,所以我能想到的就是使用循环,但我认为在这种情况下使用是错误的。我正在寻找解决方案,上面的代码不必是循环(重复)。我想要的只是如果我按下按钮 x 一定秒数,它会相应地发送上面的字母。感谢您阅读这篇相当长的文章 post。
我可以看到一些可能的方法。
1) 第一个也是最糟糕的是在每次发送后有一个 if... 来测试键状态和退出。这是非常重复的,但如果你把它放在一个函数中并只是调用它就不会太糟糕,比如:
*$x::
while (GetKeyState("x", "P")) {
sendStuff('b')
sendStuff('s')
sendStuff('c')
...
}
sendStuff(str) {
Send str
if (!GetKeyState("x", "P")) {
exit
}
sleep 1000
}
2) 接下来是继续按原样操作,使用一系列链接命令,并有一个外部的、单独的脚本在 运行 时终止该系列命令,然后重新 Run()
你的脚本,当你想重新启动。常见问题解答中介绍了杀死外部脚本,此处:http://www.autohotkey.com/docs/FAQ.htm#close
那里有三个相关部分,粘贴在这里有点长,但总而言之,您可能对以下命令感兴趣:
; Allow script's hidden main window to be detected.
DetectHiddenWindows On
; Avoid need to specify full path of file.
SetTitleMatchMode 2
; Kill another script: Update params to the script's case sensitive name.
WinClose Script Filemame.ahk - AutoHotkey
; Suspend other script.
PostMessage, 0x111, 65305,,, Script Filename.ahk - AutoHotkey
; Pause other script.
PostMessage, 0x111, 65306,,, Script Filename.ahk - AutoHotkey
; Pause/resume current script on Ctrl+Alt+P
^!p::Pause
3) 下面还有一个更长的代码示例,它描述了取消循环,我相信这是解决这个问题的正确方法,因为虽然它最初可能比较繁琐,但它的可扩展性要高得多,减少代码重复,并允许您在一个地方处理多个循环 entry/exit 条件。
简而言之,就编程风格而言,它是最好的。
将您希望发送的条目 (b, s, c, y, u) 放入字符串、数组或其他可迭代数据结构中,并对其进行迭代,以便您的 while 循环仅发送一个项目并且每次迭代暂停一次。然后,下次您按下热键时,您可以从中断的地方继续循环,也可以重新开始,具体取决于您是否保留指向结构中当前位置的指针。
例如,使用上面的 sendStuff 函数,循环将为您提供非常强大且易于扩展的功能:
*$x::
{
letters = b,s,c,y,u
Loop, parse, letters, `,
sendStuff(%A_LoopField%)
return
}
x::
index:="i"
letters:="l"
output:="o"
l:="bscyu"
i:=(i<o0?++i:1)
StringSplit,o,l
send % o%i%
sleep,1000
return
x Up::i:=0
这个post这么老了,就是忍不住
sendChars := "bscyu"
$x::
i := 1 ; (!i ? 1 : i) ; permits starting where left off.
While (getKeyState("x", "P")) {
Send % subStr(sendChars, i, 1)
i := ((i==strLen(sendChars)) ? 1 : (i+1))
if (getKeyState("x", "P")) { ; why wait if you don't have to.
Sleep 1000
}
}
文档指出 While 循环仅在每次迭代开始时进行评估,因此在循环中列出所有键只会发送所有键,然后再次在顶部跳出循环并查看不再按下“x”。