在我们开始我们的旅程之前,让我给你一些建议吧.
在本向导中,你会看到大量的文字和大量代码.
为了更有效的学习,
建议你阅读这些文字并尝试这些代码.
然后再深入学习这些代码.
你可以复制并粘贴此页上的大多数示例.
如果你弄糊涂了,试着再看一遍.
在学习使用 AutoHotkey (AHK) 之前, 你需要下载它. 下载后,你可能会需要安装它. 但这取决于你下载的版本. 对于本指南,我们将使用安装版,因为对于新手来说,它最容易设置.
视频介绍:
Frankie的 "Install and Hello World"
http://www.autohotkey.com/forum/viewtopic.php?t=77674
装完Autohotkey后,你也许会想它能做些什么. AutoHotkey不是魔法,虽然我也想. 所以需要我们告诉它要去干什么. 而这个过程叫做 "写脚本".
现在你已经创建了一个脚本,
我们需要加点内容到脚本中.
如果需要用到内置命令、函数和变量,
请查看 第5节.
这是一个使用Send命令创建的一个包含热键的简单脚本,当你按下热键后,它会向窗口发送一段文字.
^j:: Send, My First Script Return
稍后我们将进行更深入的研究.
在此之前,我们先解释一下上面的代码.
- 第一行. ^j::
是热键. ^
代表
CTRL,
j
是字母
j. 它在
::
左边 表示你将按下这个热键.
- 第二行. Send, My First Script
表示如何发送按键. SEND
是命令, 在逗号(,)之后的内容将会被发送.
- 第三行. Return
. Return将会成为你最好的朋友. 它将停止执行之后的代码.当你的脚本包含越来越多的东西时,使用Return会避免很多问题.
视频介绍:
Frankie'的"Install and Hello World"
http://www.autohotkey.com/forum/viewtopic.php?t=77674
当你在写代码的时候, 你可能有强烈的冲动想在同一行放下几个命令, 或者在一个命令中嵌套多个命令,千万不要这样做. 在第5节 我们将会告诉你为什么不要这么做, 同时,我们还将告诉你应该怎么做.
什么是热键?热键是一个发热的按键,开个玩笑. 热键是用来触发某些动作的按键或组合按键.
什么是热字串?热字串主要用于扩展你的缩写库(自动替换). 当然, 它也可以用来映射任何脚本动作.
这是一个热键:
^j:: Send, My First Script Return
这是一个热字串:
::ftw::Free the whales
这两个例子的区别在于热键CTRL & J将会触发一个事件而热字串会将你输入的"ftw"转换为"Free the whales".
"那么,该如何创建一个热键?"
好问题. 热键是通过一对::创建的. 按键名或组合按键名必须在::
左边. 代码则跟在后面, 以Return
结束.
备注: 也有例外情况,但要解释这些例外情况为时尚早, 所以我们不打算在向导页中介绍它.
esc:: MsgBox Escape!!!! Return
热字串在要触发的文本两边各有一对::. 替换后的文本在第二对::的右边.
如上所述,热字串也可以启动脚本动作. 和热键一样能干好多事,真棒!
::btw:: MsgBox You typed "btw". Return
有一个好消息是: 你可以为每一个热键、热字串、标签等 写上多行的代码.
^j:: MsgBox Wow! MsgBox this is Run, Notepad.exe winactivate, Untitled - Notepad WinWaitActive, Untitled - Notepad send, 7 lines{!}{enter} sendinput, inside the ctrl{+}j hotkey Return
符号 | 描述 |
---|---|
# | Win(Windows徽标键) |
! | Alt |
^ | Control |
+ | Shift |
& | 用于连接两个按键(含鼠标按键) 合并成一个自定义热键. |
(想要获悉更详细的符号列表, 查看热键页)
此外,这里有一个常用的按键列表:
按键列表
你可以通过在两个按键(除手柄键)之间 使用 & 来定义一个组合热键. 在下面的例子中,你要按下 Numpad0, 再按下第二个键, 才能触发这个热键:
Numpad0 & Numpad1:: MsgBox You pressed Numpad1 while holding down Numpad0. Return Numpad0 & Numpad2:: Run Notepad Return
如果你想知道热字串有没有什么酷酷的修饰符,答案是有!
热字串的修饰符在第一对::之间,例如:
:*:ftw::Free the whales
想要看更多关于热键和热字串修饰符的信息和实例, 请访问:
热键
热字串
有时候你也许想要热键或热字串只在某些特定窗口上工作(或禁用)。你可以使用#指令。
#IfWinActive
#IfWinExist
这些特殊的命令(技术上称为"指令")可以创建对上下文敏感的热键和热字串. 只需指定一个窗口标题. 但在某些情况下,你可能需要指定一个窗口句柄,组,或类. 如果想深入了解这些高级内容,点这里:#IfWinActive.
#IfWinActive Untitled - Notepad #space:: MsgBox You pressed Win+Spacebar in Notepad. Return #IfWinActive
想要关闭上下文敏感,需要将#ifwin的所有参数设置成空. 例如:
; Notepad #IfWinActive untitled - Notepad !q:: MsgBox, You pressed Alt and Q in Notepad. Return #IfWinActive ; Any window that isn't Untitled - Notepad !q:: MsgBox, You pressed Alt and Q in any window. Return
当#ifwin命令关闭(或在脚本中从未使用过), 所有的热键和热字串对所有窗口生效.
当#ifwin命令开启: 它将影响脚本中#ifwin之间的热键和热字串.
; Notepad #IfWinActive ahk_class Notepad #space:: MsgBox, You pressed Win+Spacebar in Notepad. Return ::msg::You typed msg in Notepad #IfWinActive ; MSPaint #IfWinActive untitled - Paint #space:: MsgBox, You pressed Win+Spacebar in MSPaint! Return ::msg::You typed msg in MSPaint! #IfWinActive
想要了解更多信息以及相似的命令,
查看:
#IfWinActive
为了满足一些人的特殊想法, 我在这里声明一下:AutoHotkey支持将 任意多 的热键和热字串放在一个文件中 不管是1个,还是3253个(或者更多).
#i:: run, http://www.google.com/ Return ^p:: run, notepad.exe Return ~j:: send, ack Return :*:acheiv::achiev ::achievment::achievement ::acquaintence::acquaintance :*:adquir::acquir ::aquisition::acquisition :*:agravat::aggravat :*:allign::align ::ameria::America
上面的代码是完全可以接受的. 多个热键,多个热字串,都包含在一个大的脚本文件里.
::btw::By the way ; 替换"btw"为"By the way", 当你按下结束符的时候. :*:btw::By the way ; 替换"btw"为"By the way"而不需要按下结束符. ^n:: ; Ctrl & n 热键. run, notepad.exe ; 当你按下Ctrl & n, 将启动记事本. Return ; 热键内容结束,这之后的内容将不会触发. ^b:: ; Ctrl & b 热键 send, {ctrl down}c{ctrl up} ; 复制选定的文本. 也可以使用^c, 但这种方法更加可靠. SendInput, [b]{ctrl down}v{ctrl up}[/b] ; 粘贴所复制的文本,并在文本前后加上加粗标签. Return ; 热键内容结束,这之后的内容将不会触发.
现在你决定发送一些按键到一个程序中.
你可以使用 Send 命令. Send 表示发送按键、模拟打字或按键操作.
在我们准备使用Send之前,
还有一些常见问题要注意:
就像其它热键一样,Send也有一些特殊键. Send的更多特殊键.
下面列出4个最常见的特殊键:
!: 发送ALT键击. 例如, Send This is text!a 将发送按键序列 "This is text" 并接着按下 ALT+a. 注: 在某些程序中!A 和 !a会产生不同的效果. 这是因为 !A 表示按下 ALT+SHIFT+A 而 !a 表示按下 ALT+a. 如果不确定, 请使用小写字母.
+: 发送SHIFT键击. 例如,Send +abC 会发送文本 "AbC",而 Send !+a 会按下 ALT+SHIFT+a.
^: 发送 CONTROL (Ctrl) 键击. 例如, Send ^!a 会按下 CTRL+ALT+a, 而 Send ^{Home} 则发送 CONTROL+HOME. 注: 在某些程序中 ^A 和 ^a 会产生不同的效果. 这是由于 ^A 按了 CONTROL+SHIFT+A 而 ^a 按了 CONTROL+a. 如果不确定, 请使用小写字母.
#: 发送 WIN 键击,因此 Send #e 会在按住 Windows 键时按下字母 "e".
下面一些章节主要介绍可以发送的特殊按键列表,更多详细信息可以查看 send页上的特殊按键列表.
注:
这个表并不适用于热键. 也就是说,当你使用 CTRL 或 ENTER (或其它按键) 时,不要使用 {}.
; 当你创建热键时... ; 以下是错误的脚本 {LCtrl}:: send, AutoHotkey Return ; 以下是正确的脚本 LCtrl:: send, AutoHotkey Return
上面提到的大表展示了几乎所有AHK内置的特殊按键. 比如: {enter}
和 {space}
.
有人常常认为文档中用花括号仅仅是为了好玩. 而实际上花括号是必须的. 它将告诉AutoHotkey {!}
表示 "感叹号" ,而不是要 "发送 Alt 键击". 所以要仔细查看send 页上的特殊按键列表,确保在合适的地方加上花括号.
; 注意{}中的!? 这是因为,如果没有{}, AHK 将 ; 发送 ALT 键击. send, This text has been typed{!}
; 跟上面的例子类似. AHK 将会打印单词 "enter" ... ; ... 如果enter没有加上{}的话. send, Multiple enter lines have enter been sent. ; 错误 send, Multiple{enter}lines have{enter}been sent. ; 正确
; 不要在普通单词或普通字母上加上花括号. send, {a} ; 错误 send, {b} ; 错误 send, {c} ; 错误 send, {a}{b}{c} ; 错误 send, {abc} ; 错误 send, abc ; 正确
; 下面这个例子表示按下一个键的时候再按下另一个键(或多个键). ; 如果其中一个方法不奏效,试试另外的方法. send, ^s ; 都表示发送 CTRL+s 键击 send, {ctrl down}s{ctrl up} ; 都表示发送 CTRL+s 键击 Send, {ctrl down}c{ctrl up} Send, {b down}{b up} Send, {TAB down}{TAB up} Send, {Up down} ; 按下向上键. Sleep, 1000 ; 保持1秒. Send, {Up up} ; 然后松开向上键.
send, ( Line 1 Line 2 Apples are a fruit. )
备注: Send命令有多种形式. 每种形式有其特性. 如果一种形式的send命令不能满足你的需要,可以试试另一种形式. 只需要将 "send" 命令替换成 "sendPlay" 或其它形式.
下面列出了一些常见的发送文本的命令:
Send
SendRaw
SendInput
SendPlay
SendEvent
想要了解每一个命令的详细内容, 请点这里.
非常重要!
很多游戏,尤其是新出的游戏,都有反作弊系统,例如
GameGuard, Hackshield, PunkBuster等.
如果一个游戏的反作弊系统导致你的热键、热字串和send命令统统失效,
就说明你不太走运.
且不说绕开反作弊系统是违反游戏规定的,
绕开反作弊本身也不太容易实现.
有一些方法也许能提高在某些游戏中使用热键的可能性,
但没人能打包票一定能行 . 所以,尽可能尝试所有
你能想到的办法,不要轻易放弃.
还有一个关于DirectX的问题要注意. 当你在DirectX游戏中使用AutoHotkey碰到问题时,
试试下面这个办法.
如果程序允许,尝试用窗口模式运行游戏.
这样做能够解决一些DirectX问题.
当你使用 pixel 或 image 命令时,你可能会碰到更多关于DirectX的问题.
画面颜色可能会变成黑色(0x000000),不管你设置的是什么颜色.
这是一个非常棘手的问题. 如果程序允许,试试用窗口模式运行程序.
没有万能办法能确保 AutoHotkey 能运行在所有程序里. 如果你试了所有的办法还是不行,也许 AutoHotkey 暂时无法满足你的需要.
SetKeyDelay, 0, 50
SetKeyDelay, 150, 150, Play
; 运行一个程序. 注: 大部分的程序可能需要完整路径. Run, %A_ProgramFiles%\Some_Program\Program.exe ; 打开一个网址 Run, http://ahkscript.org
你可以通过语法来分辨命令和函数. 命令后面的参数无需使用圆括号,而函数需要使用. 所以命令就像下面这样:
Command, 参数1, 参数2, 参数3
当你使用命令时,不能将几条命令放在同一行(ifEqual 除外).
也不能将一个命令作为参数插入到另一个命令.
Msgbox, Hello Run, Notepad.exe ; 错误 Msgbox, Hello, Run, Notepad.exe ; 错误 Msgbox, Hello ; 正确 Run, Notepad.exe跟函数不同的是,命令使用"传统语法". 也就是说: 当你使用
参数
时, 你需要在参数的前后加上%,比如%variable%
. 而文本和数字则不需要加双引号. This is some text
. 另外,不像函数,命令的参数不能进行运算.
注:如果确实想要在参数中进行运算,可以使用单个 %
来强制定义一个表达式, 但我们这里将不涉及这些内容.
Function(参数1, 参数2, 参数3)
SubStr(37*12, 1, 2)
SubStr(A_Hour-12, 2)
SubStr(A_Now, 7, 2)
SubStr(A_AHKPath, inStr(A_AHKPath, "AutoHotkey"))
SubStr("I'm scripting, awesome!", 16)
MyVariable:=Function(Parameters)
MyVariable:=SubStr("I'm scripting, awesome!", 16)
这不是赋值的唯一方法,但这是最常用的. 通过将函数(这个例子中的函数是 SubStr(...)
)的内容写在:=右边这种方式,将函数的返回值分配给变量 MyVariable
.
函数的更多信息
; 这些是命令 Msgbox, This is some text. StringReplace, Output, Input, AutoHotKey, AutoHotkey, ALL SendInput, This is awesome{!}{!}{!} ; 这些是函数 SubStr("I'm scripting, awesome!", 16) FileExist(VariableContainingPath) Output:=SubStr("I'm scripting, awesome!", 16)
代码块就是用一对花括号 ({ 和 }) 包围起来的一段代码,AutoHotkey 以此来判断这些代码是一个整体. 代码块经常用于 If 和 Loop 中. 如果不使用花括号,整块代码中只有第一行代码能被执行.
if (var=5) { MsgBox, var equals %var%!! Exitapp }
if (var=5) MsgBox, var equals %var%!! Exitapp
if (var=5) MsgBox, var equals %var%!! MsgBox, We are now 'outside' the if. We did not need {}'s since there was only 1 line below it.
变量就好像一个包含信息的便利贴. 它可以用于函数、命令或数学表达式中,充当存储文本、数字、数据的作用. 如果没有变量,程序和脚本将会非常乏味.
variable=text
variable=%variable2%
variable:="text"
variable:=variable2
variable:=6+8/3*2-sqrt(9)
var=%var2% some text %var3%.
var:="The value of 5+ " Variable " is: " 5+Variable
我们把(=)前面的符号称为赋值运算符, 一般都是表达式. 例如:=
+=
-=
.=
等等.
关于变量一个最常见的问题是什么时候使用百分号(%). 希望下面这些内容能够解决一些困扰.
StringLen, OutputVar, InputVar
Var = 123abc
If Var1 < %Var2%
If (Var1 != Var2) Var1 := Var2 + 100
InputBox, OutputVar, Question 1, What is your first name? if (OutputVar="Bill") MsgBox, That's is an awesome name, %OutputVar%. InputBox, OutputVar2, Question 2, Do you like AutoHotkey? if (OutputVar2="yes") MsgBox, Thank you for answering %OutputVar2%`, %OutputVar%! We will become great friends. else MsgBox, %OutputVar%`, That makes me sad.
MsgBox, 4, , Would you like to continue? IfMsgBox, No Return ; 如果选择No, 脚本将会终止. MsgBox You pressed YES. ; 用户选择了YES.
; 下面一些例子展示了什么时候该使用百分号,什么时候不该. Variable=text ; 采用"传统"方式将一个文本赋值给一个变量. VariableNumber:=6 ; 采用"表达式"方式将一个数字赋值给一个变量. Variable2=%Variable% ; 采用"传统"方式将一个变量的值赋值给一个变量. Variable3:=Variable ; 采用"表达式"方式将一个变量的值赋值给一个变量. Variable4.=Variable ; 采用"表达式"方式将一个变量的值添加到另一个变量的后面. Variable5+=VariableNumber ; 采用"表达式"方式,将两个变量的值相加,然后把结果保存到第一个变量中. Variable5-=VariableNumber ; 采用"表达式"方式,将第一个变量的值减去第二个变量的,然后把结果保存到第一个变量中. Variable6:=SubStr(Variable, 2, 2) ; 在函数中的变量. 它们永远都是表达式. Variable7=%Variable% Text ; 采用"传统"方式,将一个变量的值加上一个文本然后赋值给另一个变量. Variable8:=Variable " Text" ; 采用"表达式"方式,将一个变量的值加上一个文本然后赋值给另一个变量. MsgBox, %Variable% ; 在命令中的变量. StringSplit, Variable, Variable, x ; 在命令中的变量,但是它们作为输入或输出变量. if (VariableNumber=6) ; 如果IF采用括号的方式,那么括号中的内容就是一个表达式,所以不需要百分号. If (Variable != VariableNumber) ; 如果IF采用括号的方式,那么括号中的内容就是一个表达式,所以不需要百分号. if VariableNumber=6 ; 如果IF不使用括号,那么IF后面的内容将采用传统方式. 不过,只有赋值语句"右边"的变量需要百分号. If Var1 < %Var2% ; 如果IF不使用括号,那么IF后面的内容将采用传统方式. 不过,只有赋值语句"右边"的变量需要百分号.
对象其实是数据的一种组织方式,它有很多用处. 有时候对象被当作数组,在这重点声明一下所有的数组都是对象. 我们可以根据对象的使用范围区分不同的对象,但这些对象都有同样的特性.
MyObject := ["one", "two", "three", 17]
"one"
对应键 1
(又叫做索引号1), 值 17
对应键 4
(又叫做索引号4).
Banana := {"Shape": "Elongated", "Color": "Yellow", "Taste": "Delicious", "Price": 3}
"yellow"
对应键 "color"
. 同样的, 值 3
对应键 "Price"
.
MyObject := Array("one", "two", "three", 17)
Banana := Object("Shape", "Elongated", "Color", "Yellow", "Taste", "Delicious", "Price", 3)
:=
的左边.Banana.Consistency := "Mushy"
Banana["Pickled"] := True ; 这个香蕉烂透了.呃...
Value := Banana["Color"]
"Color"
, 其他它就是键 Color
,
我们将会得到一个值 "Yellow" , 因为我们将键 Color
与 "Yellow" 关联起来了,可以查看前面一节.
Value := Banana.Color
MyObject.NewKey := "Shiny"
MyObject["NewerKey"] := 3.1415
MyObject.InsertAt(Index, Value1, Value2, Value3...)
MyObject.Push(Value1, Value2, Value3...)
HasKey
方法得知键依然存在, 而且键也会出现在 for
循环中. (我们一会再解释for循环)
RemovedValue := MyObject.Delete(AnyKey)
MyObject[AnyKey]
的值将储存到 RemovedValue.
NumberOfRemovedKeys := MyObject.Delete(FirstKey, LastKey)
MyObject.Pop()
RemovedValue := MyObject.RemoveAt(Index)
NumberOfRemovedKeys := MyObject.RemoveAt(Index, Length)
亲爱的朋友,当你阅读到这里,说明快要结束我们这段旅程了. 我希望你有所收获. 最后,我将告诉你一些我认为你可能有用的东西. 希望你过的愉快!
ControlGetText, OutputVar [, Control, WinTitle, WinText, ExcludeTitle, ExcludeText]
ControlGetText, OutputVar
ControlGetText, OutputVar, Control, WinTitle
ControlGetText, OutputVar, Control,,, ExcludeTitle
请注意,你不能忽略参数,只是需要将它们的位置留空.
如果你像下面这样忽略"WinTitle, WinText",将会产生错误:
ControlGetText, OutputVar, Control, ExcludeTitle
语句非法.
ControlGetText, OutputVar, Control,,, ExcludeTitle
MsgBox, %A_AHKVersion%你也可以到开始菜单或安装路径下的帮助文档里面去找.
尝试和错误是非常普遍而高效的学习方法. 与动不动就问这问那相比,有时候花点时间(也许是长年累月)亲手尝试可能会学的更快.
如果你在尝试新东西的过程碰到错误,不要紧,就从解决这个错误开始. 尝试解决这个错误,一次不行就两次.多次尝试后还是解决不了,可以打开帮助文件学习哪些能做哪些不能做,然后修改你的代码再试试. 试试,失败,试试,失败,试试,试试,再试试,失败,失败,成功!
这也是很多大师们的学习经历. 不过也不要害怕提问,我们不会咬人(至少不会咬的太狠). 学习总需要时间慢慢积累,大师也不是一天练成的.
"如果一开始就碰到失败,就是要不停的尝试,再尝试." - Hickson, William E.
if (car="old") { msgbox, the car is really old if (wheels="flat") { msgbox, this car is not safe to drive. Return } else { msgbox, Be careful! This old car will be dangerous to drive. } } else { msgbox, My`, what a shiny new vehicle you have there. }使用缩进:
if (car="old") { msgbox, the car is really old if (wheels="flat") { msgbox, this car is not safe to drive. Return } else { msgbox, Be careful! This old car will be dangerous to drive. } } else { msgbox, My`, what a shiny new vehicle you have there. }关于缩进,维基百科上有很多风格示例. 建议选一种你喜欢的风格来学习.