Windows で簡単な GUI ラッパーアプリを作るなら AutoHotkey が良さそうという話

ちょっとしたツールやアプリは CUI（スクリプトやコマンド）でささっと書いちゃうことが多いのですが、UI として画面（GUI）が欲しくなる時があります。しかし GUI プログラミングは意外と面倒で、「これだ！」という手段に欠けていました。

そんな中、AutoHotkey が割と好感触で「しばらく使ってみようか」という気になったので、まとめてみます。

# 他の選択肢と AutoHotkey について
まずは他の選択肢と、最後に今回の主役である AutoHotkey について所感をまとめます。

## PowerShell
Windows にデフォで同梱されている強力なスクリプト環境で、GUI もバリバリ書けますが、

- 動作が重い
- 構文が Java みたく長くなりがちで書きづらい
- デフォ同梱と言いつつ、そのまま配布しても使えなかったりする（権限設定など少し追加手順が必要となることが多い）
- 言語仕様とか雰囲気とかなんかあまり好きになれない

というわけでイマイチ。

## Excel VBA
Excel には VBA の IDE が備わっていて、Excel 一つで VBA プログラミングがバリバリできます。GUI もグラフィカルに D&D で配置したりできるので簡単に作れます。が、

- 動作に Excel が必要
- 実行ファイル化できない
- VBA の言語仕様が古くて（例: 配列の添字が 1-origin だとか **下限** があるとか）イライラする
- そもそも Excel は使いたくない

というわけでこれもイマイチ。

## C/C++
いわゆる低級言語の代名詞で、その気になれば何でもできますが、

- 低級すぎて書くのが辛い（例: 文字列操作にも一苦労）
- GUI 部分は一から Windows プログラミングが必要
- インタプリタでない（コンパイルするのだるい）
- IDE が無いと辛い
- IDE が重い

というわけで正直勘弁してほしいですね。

## LL(Python, Ruby)
いわゆる Lightweight Language というやつで、Python や Ruby などはこのカテゴリです。GUI は専用のフレームワーク(Python なら TKinter, wxPYthon, Kivy, あと頑張れば Electron 等)を使うことで書けます。書き慣れている場合はおそらく一番楽なのですが、

- そのフレームワークの使い方が複雑で、習得が大変
- コード量が多く、また煩雑になりがち(クロスプラットフォームを担保してあるためどうしても汎用性/抽象性が高まる)
- 実行ファイル化に苦労する

と慣れるまでが大変です（実際何回か軽く挑んでみては挫折してますし :sweat:）

また、Windows には LL がデフォルトで同梱されていないので、他の人にも使ってもらう GUI の場合は大体実行ファイル化が必須になるわけですが、その実行ファイル化が大変なんですよね。私は Python で[cx_Freeze](https://anthony-tuininga.github.io/cx_Freeze/) を使っているのですが、 [ブログ記事にも書いている通り色々と苦戦します](http://stakiran.hatenablog.com/archive/category/cx_Freeze)。

もうちょっと楽したいな、というのが本音です :smirk:

## Electron(Node.js)
最近見かけるようになった GUI フレームワークで、（確か）GitHub のデスクトップクライアントやら Visual Studio Code やらはこれで開発されていたりします。Javascript を使って開発できるのは便利だとは思うのですが、上記 LL のデメリットに加えて、

- 動作が重い
- 実行ファイルサイズが大きい(数十MB超)
- IDE が無いと苦しい

というわけで、ちょっとした GUI を書くのには正直辛いです。

## 超高級言語(HSP, なでしこ)
[HSP](http://hsp.tv/) は小中学生でもゲームが作れる言語で、[なでしこ](https://nadesi.com/top/) は日本語で書く言語です。どちらも処理が非常に高級で、たとえばウィンドウ生成も命令一つでサクっと表示できたりします。確かに GUI は作りやすいですし、実行ファイル化も割と楽なのですが、

- 言語仕様が貧弱 or 異質で書きづらい
  - [HSPについてはこちらが詳しいです](https://qiita.com/YSRKEN/items/0c059abfb8685051cb16)
  - なでしこは日本語ですし……
- 「任意のコマンドラインを実行する」という点で弱い
  - 特になでしこは当該機能をサポートしていない（もしかしたらあるのかもしれませんが）
  - スクリプトやらコマンドラインを叩くだけのラッパー、的な GUI が多いのでこの点は重要です
- 付属エディタ（使いづらい）の使用を強制される
  - たとえば HSP は付属のスクリプトエディタ上でしか実行ファイル化を行なえません（一応コンパイラが独立して存在していますが使い方が煩雑でよくわかりませんでした）

惜しいですが不採用です。

## AutoHotkey
最後に AutoHotkey です。これも超高級言語の部類に入ると思いますが、

- GUI プログラミング(ウィンドウや各種フォームをつくる)が [割と楽](http://ahkwiki.net/GUI)
- 動作が重くない
- 他のプログラムやスクリプトも呼び出しやすい
- 実行ファイル化できる
  - ビルドするのが簡単
  - 実行ファイルは単体で動作する（他ランタイムのインストールは不要）
- デフォルトでタスクトレイアイコンが追加され（デバッグ等に）地味に便利(※1)
  - 設定で非表示にもできます

私には「おっ、結構良くね？」と思えました。

※1 トレイアイコンはこんな感じです

![ahk_default_trayicon.jpg](https://qiita-image-store.s3.amazonaws.com/0/191170/cb42c733-ded8-b752-33ba-61c6cb926050.jpeg)

# AutoHotkey とは
簡単に紹介しておきます。

[AutoHotkey](https://autohotkey.com/) とは Windows 用のスクリプトエンジンです。

ahk ファイルという独自文法で書いたスクリプトを AutoHotkey.exe に食わせることで動作します。元々はその名の通りキーボード制御（リマップやらホットキーやら）用ソフトウェアでしたが、色んな機能を搭載するようになり、今では

- [2018/05/14 現在で 1700 star](https://github.com/Lexikos/AutoHotkey_L)
- AHK の文法は [GitHub のシンタックスハイライトとしても採用](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml#L325) されている

強力なスクリプト言語にまで成長しました。

## インストール
[公式サイト](https://autohotkey.com/download/) からインストーラを落としてインストールするだけです。

バージョンは安定版の 1.1.X が良いでしょう。ちなみにこのバージョンは AutoHotkey_L とも呼ばれます（「え？Lって何？」と混乱しないように）。

## ドキュメント
Wiki が充実しています。

基本的には [AutoHotkey Wiki](http://ahkwiki.net/Top) か、あるいは同梱のヘルプファイル（英語ですが）で事足ります。

「～～がしたい」といった時にはググると良いでしょう。大体ドンピシャの答えが見つかります。日本語だけでなく [英語でググると捗る](https://qiita.com/sta/items/7f600ac5497f81173fc7) こともあります

## 実行ファイル化する
ahk ファイルは AutoHotkey がインストールされてないと実行できませんが、実行ファイル化しておくと他の環境でも動きます（追加のランタイム等も不要です）。

### 実行ファイル化方法
Ahk2Exe というコンパイラを使うだけです。

- AutoHotkey 付属のツール Ahk2Exe.exe を使う
- `/in` 引数に実行ファイル化したい ahk スクリパス
- `/out` 引数に生成する実行ファイル名

他にもオプションはあります。GUI ツールもあります。

### サンプル
一つ例を挙げます。

`Run "C:\Program Files\AutoHotkey\Compiler\Ahk2Exe.exe" /in "%A_ScriptFullPath%" /out "%A_ScriptDir%\menu.exe"`

システム変数を使っちゃってますが、`%A_ScriptFullPath%` は今実行中の ahk スクリプトのフルパス、`%A_ScriptDir%` はそのディレクトリを表すので、上記は結果的に「自分自身（今実行中の ahk スクリプト）を実行ファイル化し、生成した実行ファイル menu.exe を同じディレクトリに保存」という処理になります。

# 今回作ってみたもの
今回試しにつくってみた成果物について簡単にまとめます。

## つくったもの
[Wrapopup](https://github.com/stakiran/wrapopup)

![gui_menu_wrapper_with_autohotkey](https://user-images.githubusercontent.com/23325839/39992829-fa7467ca-57ae-11e8-90ee-b27f082179c9.jpg)

ポップアップメニューを表示し、選択した項目に対応する操作（コマンドラインなど）を実行するだけのラッパー GUI です（厳密に言うとそのような GUI を作るためのテンプレートです）。

上記画像は [MDWiki](https://qiita.com/sta/items/a1ee3537ce6e7cfe34a8) を使った ひとり Wiki プロジェクトなのですが、ビルドやら Git 操作やら叩くコマンドが多くて覚えきれず、またマウス操作がしばしば発生するためコマンドだと使いづらい時もある、ということで今回このような GUI ラッパーを作ってみたという経緯があります。

## ファイル構成
ファイルは以下二つのみです。

- menu.ahk …… エントリーポイントです
- menu_config.ahk …… 環境固有情報を指定したファイルです

menu.ahk を実行するとポップアップメニューが表示される、という使い方です。

## メニューを拡張する
一応テンプレートなので、好き勝手に拡張できるようにしてあります。簡単に書くと

- `menu_creation` ラベル内でメニュー項目を定義する
- 各項目に対する実行内容を `label_XXXX` ラベル に定義する

の 2 ステップで自由にメニュー項目（と選択時の処理）を拡張できるようにしてあります。

以下にスクリプトの全体構造を載せてきます。

```ahk
ahk_options:

; ここに AHK 関連の設定を書く.
; 設定一覧は http://ahkwiki.net/Commands_Name あたりを参照のこと.

configs:

; ここで外部スクリプトを Include する.
; 本スクリプトでは menu_config を Include している.
; (menu_config にはテキストエディタパスなど環境固有情報を書く.)
#Include %A_ScriptDir%\menu_config.ahk

menu_creation:

; ここでポップアップメニューを作る.
; 詳しい文法は http://ahkwiki.net/Menu を参照.
Menu, menuname1, Add, &Build,       label_build_this_script
...

menu_showing:

; ここでメニューを表示する.
; ... (表示位置を決めてから) ...
Menu, menuname1, Show, %showx%, %showy%
Return

; 各メニュー項目に対するサブルーチン.
; -----------------------------------

label_build_this_script:
; ...
Return

; サブルーチン.
; -------------

; マウス座標を取得.
get_mouse_pos(){
  MouseGetPos, mousex, mousey

  mousepos := {}
  mousepos.x := mousex
  mousepos.y := mousey
  Return mousepos
}

; ... サブルーチンが続く... 
```

# 今回つくってみての所感

## 良い点
- GUI 作るのが楽
  - ウィンドウやらフォームやらを作るのに煩雑な Windows プログラミングをしなくてもいい
- その割にはオプションがきめ細かく、かゆいところに手が届く
- 情報が豊富なので理解・習得・解決しやすい
- 実行ファイル化が楽
- 動作も重くなく、また安定している

他の手段よりも楽だな、と改めて思いました。

## 悪い点
- 未定義変数をエラーにしてくれないので Typo 時など地味にハマる
- 代入演算子 `=` と `:=` の使い分けがややこしくてよくハマる
- その他 [スクリプト仕様](http://ahkwiki.net/Scripts) に微妙なクセや罠があり、ちらちらハマる
- 実行ファイルサイズがやや大きい(上記成果物では 800KB)

慣れるまでは意外と苦戦します。Wiki や Google は手放せません。

# 参考
- [AutoHotkey Wiki](http://ahkwiki.net/Top)
  - 国内で最も充実しているリファレンス
- [GUI - AutoHotkey Wiki](http://ahkwiki.net/GUI)
  - ウィンドウやフォームなど GUI 絡みはこちら
- [AutoHotkeyのチュートリアルを読んだ - もうカツ丼でいいよな](http://d.hatena.ne.jp/Rion778/20091208/1260241968)
  - プログラマ向けに端的にまとまってある
- [AutoHotkey スクリプトを ahk2exe でコンパイルしてつくった実行ファイルの仕様 - stamemo](http://stakiran.hatenablog.com/entry/2018/05/10/194620)
  - 自分で書いた記事ですが ahk2exe に関する話
- [[AHK基礎] AutoHotkeyはどんな言語か - ITジョー](https://itjo.jp/autohotkey/what-is-autohotkey/)
  - GUI 作って配布しやすいことを端的に説明＆検証している

# おわりに
以上、Windows で簡単な GUI ラッパーアプリを作る際の手段として AutoHotkey が良さそう、という話でした。参考になりましたら幸いです。

また、間違いやオススメ等ありましたらコメントください :smile: