ahk使いはF13-F24キーを活用すべし


# ahk最強

ahkことAutoHotkeyとは、Windows作業の自動化に大いに役立つスクリプト言語である。ちょっと癖の強い言語だが、一通りのことはできる。高度な正規表現も扱える。簡易GUIも作成できる。クラスやライブラリも扱える。少なくとも単なるキーマップツールなどではない。

次に示す自作関数は、一般には大して役に立たないだろうが、あくまでこういうことが出来るというデモである。

```ahk:sample.ahk
; 画面を12分割の12分割の12分割の12分割した領域をqwer/asdf/zxcvで順次指定(Tabで離脱可)してそこをクリックする。
; 例えば、関数を呼びだしてからrrと押すと右上の隅が拡大表示されてそこからさらに最大2回12択してクリック位置を指定できる。
; CaptureScreen.ahk使用
DrawHint2Click(x, y, w, h){
    Gui, DHint:+LastFound +AlwaysOnTop -Border -Caption +ToolWindow

    if(w < 200){
        file = %A_Temp%\dhint.png
        CaptureScreen(x ", " y ", " x+w ", " y+h, , file)
        disph := A_ScreenHeight, dispw := disph * w / h
        dispx := (A_ScreenWidth - dispw) / 2, dispy := 0
        Gui, DHint:Add, Picture, w%dispw% h%disph%, %file%
        Gui, DHint:Show, center NA
    }else{
        Gui, DHint:Color, F0F0FF
        WinSet, TransParent, 100
        Gui, DHint:Show, x%x% y%y% w%w% h%h% NA
        dispx := x, dispy := y, dispw := w, disph := h
    }

    dispw0 := dispw/4, disph0 := disph/3
    Loop, 3 {
        dispx_i := (dispw0 * A_Index - 1) + dispx
        Gui, DHintV%A_Index%:+LastFound +AlwaysOnTop -Border -Caption +ToolWindow
        Gui, DHintV%A_Index%:Color, Blue
        Gui, DHintV%A_Index%:Show, x%dispx_i% y%dispy% w1 h%disph% NA
    }
    Loop, 2 {
        dispy_i := (disph0 * A_Index - 1) + dispy
        Gui, DHintH%A_Index%:+LastFound +AlwaysOnTop -Border -Caption +ToolWindow
        Gui, DHintH%A_Index%:Color, Blue
        Gui, DHintH%A_Index%:Show, x%dispx% y%dispy_i% w%dispw% h1 NA
    }

    SetTimer, destroyDHint, -5000

    Input, inp, C T5, {Escape}{Tab},q,w,e,r,a,s,d,f,z,x,c,v
    GoSub, destroyDHint
    delta := ({
        (Join
        "q": [0, 0], "w": [1, 0], "e": [2, 0], "r": [3, 0],
        "a": [0, 1], "s": [1, 1], "d": [2, 1], "f": [3, 1],
        "z": [0, 2], "x": [1, 2], "c": [2, 2], "v": [3, 2]
        )})[inp]

    if ErrorLevel = EndKey:Escape
        return
    w0 := w/4, h0 := h/3
    if(inp <> "")
        x := x + delta[1] * w0, y := y + delta[2] * h0
    else
        x := x + w/2, y := y + h/2, w0 := 0, h0 := 0
    if(w0 > 200/16){
        DrawHint2Click(x, y, w0, h0)
    }else{
        x := x + w0/2, y := y + h0/2
        CoordMode, Mouse, Screen
        SendInput, {Click %x%, %y%}
    }

    destroyDHint:
        Gui, DHint:Destroy
        Gui, DHintV1:Destroy
        Gui, DHintV2:Destroy
        Gui, DHintV3:Destroy
        Gui, DHintH1:Destroy
        Gui, DHintH2:Destroy
    return
}

; Alt+Ctrl+Cで関数を呼び出す
!^c::
DrawHint2Click(0, 0, A_ScreenWidth, A_ScreenHeight)
return
```

# 押しっぱなし問題とF13-F24キー

ahkは便利だが、使ってみると分かるがたまにキーが押しっぱなしになるという重大な罠がある。これをどう解決するかの1つの答えが、F13-F24キーである。これらのキーは通常使われないため押しっぱなしになっても副作用が生じにくい。また、キーバインドの枯渇・重複問題の回避にもなる。

前掲のプログラムの末尾はこのように書き換えると具合がよろしい。F13キーをShift, Ctrl, Altのような修飾キーとして使っていることに注目してほしい。

```ahk:sample2
; F13キーとcキーを同時に押すと関数が呼ばれる
F13 & c::
DrawHint2Click(0, 0, A_ScreenWidth, A_ScreenHeight)
return
```

# ところでどうやってF13-F24を入力するのか

手持ちのキーボードにF13-F24がなくても大丈夫。keyswapなどのレジストリレベルのキーマップ変更ツールを使えばよい。どのキーを変えるかは重要だが、無変換キーや変換キーやCapsLockキーなどがホームポジションから押しやすく推奨される。

キーマップを変えた上で元の機能を潰したくない場合はこうする。ここではF13キーを修飾キーのように使いつつ、IMEトグルと全角かな/全角英数トグルの機能も持たせている。

```ahk:sample3
; F13キー単体でIMEトグル。IMEオンの状態で連打すると全角のかな/英数をトグルする。(IME.ahk使用)
; ※Ctrl+Shift+[, Ctrl+Shift+]でかな/英数がトグルするのはATOK側の設定
F13::
if(A_PriorHotKey = A_ThisHotKey && A_TimeSincePriorHotkey < 400 && IME_GET() = 1){
    if(IME_GetConvMode() = 8)
        Send, ^+{[}
    else
        Send, ^+{]}
}else{
    IME_SET(IME_GET() = 1 ? 0 : 1)
}
```

# フットペダルや左手デバイスもあるよ

CAD使いや一部のイラストレーターやゲーマーにはよく知られている、フットペダルや左手デバイスといった入力デバイスを使い、そこに特殊なキーを割り当てるという方法もある。私はフットペダルにF14-F16を割り当てている。

フットペダルの利便性は特に説明不要だろう。2本の手だけでなく足でも操作できることによって、修飾キーつきの複合的な入力の自由度が広がる。例えば変換キーをF13にした場合には変換キーは右側にあるのでF13 & 9のような右側どうしで組み合わせる入力がちょっとやりにくい、といったことに頭を悩ますことはもうなくなる。

左手デバイスは聞き慣れない方もいると思うので少し説明すると、利便性が大きく分けて2つある。1つはマウス操作時にポータブルなデバイスを左手で握りながらキーボードに手を戻すことなく色んな操作ができること。もう1つはBluetoothによって座席から離れても操作ができること。ahkからはジョイスティックとしてプログラミングできる。例えば、ペンの色・種類を左手でスムースに変えながら右手で絵を描く、席を離れて散策しながら音楽をディグる、といった使い方ができる。


# #Ifディレクティブを使ったりアプリ別のスクリプトと連携したり

\#IfディレクティブとWinActive()を組み合わせれば、アクティブなアプリやウィンドウのタイトルに応じて処理を分けることもできる。

例えば、Webページの特定の箇所のスクショを撮りたいという状況にはよく遭遇する。そんな時に、Google Chromeのnode screenshot機能なら特定のDOM要素だけを切り出せるのでうってつけに思えるが、DevToolsを開く必要があって手動だと手間がかかってしまう(Chromeの内部に通じた人なら簡易に呼び出せそうだが)。そこでnode screenshotを自動化してみたい。

```ahk:sample4
; chrome一般
; ※Set_TitleMatchMode()はSetTitleMatchModeで設定する自作関数
#If Set_TitleMatchMode("RegEx") and WinActive("- Google Chrome$ ahk_exe")

; マウスカーソル下の要素のnode screenshotをとる
F13 & n::
SendInput, {Click R}
Sleep, 50
SendInput, {Up}{Enter}
WinWaitActive, DevTools, , 2
Sleep, 200
SendInput, {AppsKey}
Sleep, 200
SendInput, {c 4}{Enter}
Sleep, 500
SendInput, ^w
return()

#If
```

こうしたキー操作はTampermonkeyなどのユーザースクリプトでもある程度は行えるが、DevToolsのようなWebページではないウィンドウの操作には対応できない。かといってブラウザの拡張を作るのは大袈裟すぎる。そんなときにahkなら簡単に自動化スクリプトが組める。

そうして自動化した処理にキーをどんどん割り当てるには、F13-F24キーのような通常用いないキーを修飾キーに使うのがよい。Alt, Ctrl, Shiftだけだと気になるキーの枯渇や衝突を気にすることなくガンガン追加できる。

ファンクションキーに併せて、Inputコマンドを用いてマルチストロークキーを定義するのもキーバインドが整理されてよい。この際にスプラッシュなどでナビゲートを表示するとなおよい(下例)。

```ahk:sample5
EditText(){
    ; テキスト編集ツール

    SplashTextOn, 500, 300, テキスト編集ツール,
    (LTrim
    次のどれかを入力

    =置換
    q: クォート, ue: URIエンコード, s1: 半角スペース区切り, s2: 全角スペース区切り
    m: メールエスケープ, fe: ファイル名エスケープ

    =挿入
    d: 日付時刻, p: 履歴結合, or: OR結合(検索ワード用)

    =アプリ起動

    ; ｟中略｠

    )
    Input, tool, C I T3, {Enter}, q,ue,s1,s2,m,d,a,fe,p,or
    SplashTextOff

    If ErrorLevel = Match
    {
        ; ### 置換 ###
        If tool = q
        {
            CopySelection()
            s := GetQuotedString(clipboard)
            InsertText(s)
        }
        else if tool = ue

    ; ｟以下略｠
```

サイトやDOM要素をきめ細やかに区別して処理するには、ImageSearchコマンドで画面内を画像検索したり、ブラウザ側でTampermonkeyスクリプトなどを用いてスタイリングする(例えば色分けする)といった解決策が有効なことが多い。そしてそうやって細かく処理できればできるほど、通常の修飾キーではやはり足りないと痛感する。