Ahk学习笔记

Posted by wsxq2 on 2019-05-06
TAGS:  ahkWindows脚本TODO

本文最后一次编辑时间:2019-05-11 12:33:36 +0800

  AutoHotkey是面向普通计算机用户的自由开源的自动化软件工具,它让用户能够快捷或自动执行重复性任务[2]。为了保持AutoHotkey自由开放、持续开发,2014年4月成立了AutoHotkey Foundation以提供组织、法务和财政上的支持。[3]

  与同类工具比较,AutoHotkey体积小巧、语法简明使其易学易用,同时在热键、热字符串实现的快捷、高效(同时也强大,这点其他语言也能做到)方面没有其他语言能超越,不过缺点同样明显,即没有官方自带或第三方实现的完善的标准库[4],这样需要实现未内置的功能时通常需要直接调用Windows API或寻找别人封装好的函数(注:命令行命令或COM等与Windows API在功能全面性上相差太远)。换句话说,普通人极容易使用,但熟悉后要提升复杂性以实现更强大的功能时则困难重重,这点从大量用户选择该语言入手而后一些需求较高的用户则转向其他语言容易看的出来。例如,Folder Menu v2及之前的版本使用AutoHotkey,v3时换为AutoIt。[5]

  引用自 AutoHotkey - 维基百科,自由的百科全书

常用链接

AutoHotkey 学习指南 - AutoHotkey Community

ahkcn.sourceforge.net

www.autohotkey.com/boards/

热键之组合键与序列键 - AutoHotkey Community: https://www.autohotkey.com/boards/viewtopic.php?t=4287

其它

AHK 中全局变量、局部变量和静态变量的用法和区别 - 陌辞寒的技术博客 - SegmentFault 思否

遇到的问题

在不安装 ahk 的情况下运行脚本?

详情参见 Run script without AutoHotKey installed - Ask for Help - AutoHotkey Community

使用快捷方式

Autohotkey.exeYourScript.ahk放到同一目录中,并创建一个快捷方式,指向Autohotkey.exe并传递参数YourScript.ahk

编译脚本

使用Ahk2Exe.exe编译你的脚本为.exe文件,甚至可以给它加壳

使用注册表

运行如下注册表文件:

1
2
3
4
5
6
7
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\.ahk]
@="AutoHotkeyScript"

[HKEY_CLASSES_ROOT\AutoHotkeyScript\Shell\Open\Command]
@="\"\\workstation01\C:\\Program Files\\AutoHotkey\\AutoHotkey.exe\" \"%1\" %*"

实践记录

打开雷电模拟器并启动触动精灵并启动王者荣耀刷金币脚本

has_started(ldname)
{
    IfWinExist %ldname%
    {
        WinActivate
        PixelGetColor color1, 67,510,RGB ;左下角
        PixelGetColor color2, 1241, 61,RGB ;时间图标中下面的冒号
        PixelGetColor color3, 639, 608,RGB ;中间部分的小白点
        return (!(color1==0x009d14) && color2==0xFFFFFF && color3==0xF5F5F5) ;color1不为蓝色,color2为白色,color3为白色时表示雷电模拟器启动完成
    }
    return false
}
has_enter_TS(ldname)
{
    IfWinExist %ldname%
    {
        WinActivate
        PixelGetColor color1,236,87,RGB ;“触动精灵”的背景
        PixelGetColor color2,526,173,RGB ;“脚本”、“其他”的背景
        PixelGetColor color3,419,723,RGB ;“我的脚本”、“找脚本”、“我的账号”的背景
        return color1==0x141414  && color2==0xF0F0F0 && color3==0xF0F0F0 ;color1为黑色,color2为白色,color3为白色时表示进入了TS
    }
}

main()
{
    runwait ldconsole.exe globalsetting --fps 20 --audio 1  --fastplay 1
    ld_nums:=2 ;模拟器数量
    ld_nameprefix:="ld" ;模拟器名字前缀(结合ld_nums表示ld0, ld1这两个模拟器)
    i:=0
    while (i<ld_nums)
    {
        runwait ldconsole.exe launch --name %ld_nameprefix%%i%
        Sleep 5000
        i++
        if not KeepwjRunning
            return
    }
    Sleep % 10*1000
    i=0
    while ( i<ld_nums )
    {
        if(has_started(ld_nameprefix i))
        {
            runwait ldconsole.exe runapp --name %ld_nameprefix%%i% --packagename com.touchsprite.android
            i++
        }
        Sleep 2000
        if not KeepwjRunning
            return
    }

    i=0
    while ( i<ld_nums )
    {
        if(has_enter_TS(ld_nameprefix i))
        {
            Sleep 5000
            runwait %comspec% /c ldconsole.exe action --name %ld_nameprefix%%i% --key call.keyboard --value volumedown
            i++
        }
        Sleep 2000
        if not KeepwjRunning
            return
    }
    runwait ldconsole.exe sortWnd
}

test()
{
    if(has_started("ld0")){
        ToolTip has_started

    }
    else{
        ToolTip not has_started
    }
    ;IfWinExist, 无标题 - 记事本
    ;    WinClose ; use the window found above
    ;else
    ;    WinClose, Calculator

}

^!t::
    test()
return

;王者荣耀刷金币
#MaxThreadsPerHotkey 3
~w & j::
    #MaxThreadsPerHotkey 1
    WinGetActiveTitle, WinTitle
    if (WinTitle != ""){
        return
    }
    if KeepwjRunning  ; 这说明一个潜在的 线程 正在下面的循环中运行.
    {
        KeepwjRunning := false  ; 向那个线程的循环发出停止的信号.
        return  ; 结束此线程, 这样才可以让下面的线程恢复并得知上一行所做的更改.
    }
    ; 否则:
    global KeepwjRunning := true
    main()
    ;test()
    KeepwjRunning := false  ; 复位, 为下一次使用热键做准备.
return

~w & k::
run "D:\Changzhi\dnplayer2\ldconsole.exe" quitall
return

打开 Virtual Box 中名为 master 的虚拟机并使用 putty 连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
;master virtualbox
~m & v::
    run "C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" startvm master --type headless,,Hide
    Sleep 40000
return
;master putty
~m & p::
    run "C:\Program Files (x86)\MTPuTTY\mtputty.exe",,Hide
    Sleep 500
    WinWaitActive % "MTPuTTY (Multi-Tabbed PuTTY)"
    Click 93,191
    Send {Enter}
return
;master kill
~m & k::run "C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" controlvm master acpipowerbutton

关闭所有程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
;close all
#MaxThreadsPerHotkey 3
~c & a::
    #MaxThreadsPerHotkey 1
    if KeepcaRunning  ; 这说明一个潜在的 线程 正在下面的循环中运行.
    {
        KeepcaRunning := false  ; 向那个线程的循环发出停止的信号.
        return  ; 结束此线程, 这样才可以让下面的线程恢复并得知上一行所做的更改.
    }
    ; 否则:
    KeepcaRunning := true
    lastWinTitle:="aaa"
    while true
    {
        Sleep 500
        ;ToolTip %KeepcaRunning%
        if not KeepcaRunning
            break  ; 跳出此循环.
        WinGetActiveTitle, WinTitle
        ;ToolTip %lastWinTitle%
        if ( lastWinTitle="关闭 Windows" || lastWinTitle="")
        {
            break
        }
        lastWinTitle:=WinTitle
        ToolTip %WinTitle%
        if (WinTitle="Windows PowerShell")
        {
            send {Esc}exit{Enter}
        }
        else if (WinTitle="任务管理器")
        {
            Click 972,13
            continue
            send !fx
        }
        else if (WinTitle="master - PuTTY")
        {
            send ^u^d
            Sleep 500
            send !{F4}
        }
        ;{
        ;continue
        ;}
        else
        {
            send !{F4}
        }
        send !{Tab}
    }
    KeepcaRunning := false  ; 复位, 为下一次使用热键做准备.
return

任意编辑器中的上下文帮助

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
;changed from http://ahkcn.sourceforge.net/docs/scripts/ContextSensitiveHelp.htm

; 任意编辑器中的上下文帮助 start

; 下面的热键使用剪贴板来实现与最大数目的
; 编辑器兼容 (因为 ControlGet 在大多数高级编辑器中无法工作).
; 它会在之后恢复剪贴板原来的内容, 但只是纯文本,
; 这样似乎比什么都不做要好.

$^2::
; 下面的值只在此热键执行期间有效.
; 因此, 不需要恢复它们原来的值
; 因为在线程结束时会自动进行这个操作:
SetWinDelay 10
SetKeyDelay 0
AutoTrim, On

if A_OSType = WIN32_WINDOWS  ; Windows 9x
    Sleep, 500  ; 提供一些时间让用户释放按键.

C_ClipboardPrev = %clipboard%
;MsgBox %clipboard%
clipboard =
; 如果有高亮的单词, 则使用它 (因为有时用户可能
; 故意高亮一些不是命令的内容):
Send, ^{Insert}
ClipWait, 0.1
if ErrorLevel <> 0
{
    clipboard=%C_ClipboardPrev%
}
C_Cmd = %clipboard%  ; 这样会移除前导和尾随的 tab 和空格.
clipboard = %C_ClipboardPrev%  ; 恢复剪贴板为原来的内容.
Loop, parse, C_Cmd, %A_Space%`,  ; 命令末尾的首个空格或逗号.
{
    C_Cmd = %A_LoopField%
    break ; 即我们只需要循环一次.
}
IfWinNotExist, AutoHotkey Help
{
    ; 判断 AutoHotkey 的位置:
    RegRead, ahk_dir, HKEY_LOCAL_MACHINE, SOFTWARE\AutoHotkey, InstallDir
    if ErrorLevel  ; 没有找到, 所以在其他一些常见位置寻找.
    {
        if A_AhkPath
            SplitPath, A_AhkPath,, ahk_dir
        else IfExist ..\..\AutoHotkey.chm
            ahk_dir = ..\..
        else IfExist %A_ProgramFiles%\AutoHotkey\AutoHotkey.chm
            ahk_dir = %A_ProgramFiles%\AutoHotkey
        else
        {
            MsgBox Could not find the AutoHotkey folder.
            return
        }
    }
    Run %ahk_dir%\AutoHotkey.chm,,Hide
    WinWait AutoHotkey Help
}
; 上面设置了我们下面要使用的 "最后找到的" 窗口:
WinActivate
WinWaitActive
StringReplace, C_Cmd, C_Cmd, #, {#}
send, !n{home}+{end}%C_Cmd%{enter}
return

; 任意编辑器中的上下文帮助 end

添加拼写错误 HotString 到当前脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
;cut from http://www.autohotkey.com/download/AutoCorrect.ahk start
;------------------------------------------------------------------------------
; Win+H to enter misspelling correction.  It will be added to this script.
;------------------------------------------------------------------------------
#h::
; Get the selected text. The clipboard is used instead of "ControlGet Selected"
; as it works in more editors and word processors, java apps, etc. Save the
; current clipboard contents to be restored later.
AutoTrim Off  ; Retain any leading and trailing whitespace on the clipboard.
ClipboardOld = %ClipboardAll%
Clipboard =  ; Must start off blank for detection to work.
Send ^c
ClipWait 1
if ErrorLevel  ; ClipWait timed out.
    return
; Replace CRLF and/or LF with `n for use in a "send-raw" hotstring:
; The same is done for any other characters that might otherwise
; be a problem in raw mode:
StringReplace, Hotstring, Clipboard, ``, ````, All  ; Do this replacement first to avoid interfering with the others below.
StringReplace, Hotstring, Hotstring, `r`n, ``r, All  ; Using `r works better than `n in MS Word, etc.
StringReplace, Hotstring, Hotstring, `n, ``r, All
StringReplace, Hotstring, Hotstring, %A_Tab%, ``t, All
StringReplace, Hotstring, Hotstring, `;, ```;, All
Clipboard = %ClipboardOld%  ; Restore previous contents of clipboard.
; This will move the InputBox's caret to a more friendly position:
SetTimer, MoveCaret, 10
; Show the InputBox, providing the default hotstring:
InputBox, Hotstring, New Hotstring, Provide the corrected word on the right side. You can also edit the left side if you wish.`n`nExample entry:`n::teh::the,,,,,,,, ::%Hotstring%::%Hotstring%

if ErrorLevel <> 0  ; The user pressed Cancel.
    return
; Otherwise, add the hotstring and reload the script:
FileAppend, `n%Hotstring%, %A_ScriptFullPath%  ; Put a `n at the beginning in case file lacks a blank line at its end.
Reload
Sleep 200 ; If successful, the reload will close this instance during the Sleep, so the line below will never be reached.
MsgBox, 4,, The hotstring just added appears to be improperly formatted.  Would you like to open the script for editing? Note that the bad hotstring is at the bottom of the script.
IfMsgBox, Yes, Edit
return

MoveCaret:
IfWinNotActive, New Hotstring
    return
; Otherwise, move the InputBox's insertion point to where the user will type the abbreviation.
Send {HOME}
Loop % StrLen(Hotstring) + 4
    SendInput {Right}
SetTimer, MoveCaret, Off
return

链接

下面总结了本文中使用的所有链接: