IME(日本語入力)において長音記号〈音引き〉の入力には通常マイナスキーを押すでしょう。僕も右小指でマイナスキーを押して長音記号を入力していたのですが、このとき右肘を外に回転させる動作が気になってきました(歳のせいでしょう)。肘・指の動作を少なくするように設定しました。
途中で予想外のことが起こり、けっこう手間取ってしまいました。
内容:
やりたかったこと/やったこと
日本語キーボードだと、右シフトキーの左隣に「\, _, ろ」の三文字が刻印されたキーがあります。このキーは、半角モード(IMEがOFF状態)ではASCII文字(Unicode の Basic Latin の文字)のバックスラッシュ(U+005C)の入力に使われます。シフトするとアンダースコア(U+005F)が入力されます。全角モード(IMEがON状態)だと、(原則的には)対応する全角文字(Unicode の Fullwidth ASCII variants の文字)「¥」「_」が入力されます。「バックスラッシュと円マークが対応する文字なのか?」に関しては、とてもゴチャゴチャした歴史的経緯があります(が、もう興味ないので割愛)。このキーを、刻印されているメインの文字からバックスラッシュキーと呼ぶことにします。
マイナスキー(刻印は「-, =, ほ」)は上段にあって遠いので、代わりにバックスラッシュキーで長音記号(U+30FC の文字*1)を入力しよう、というのが最初の発想です。アンダースコアと長音記号は似てるので、アンダースコア入力(シフト+バックスラッシュキー)を長音記号入力に置き換えちゃえ、ということです。置き換えには Autohotkey を使います。
試してみたら、シフトキーを押すのはバカバカしいと気づきました。キーストロークと入力は次のように対応させます。
- 半角モード、バックスラッシュキー : バックスラッシュ文字(「\」) が入力される
- 半角モード、シフト+バックスラッシュキー : アンダースコア文字(「_」) が入力される
- 全角モード、バックスラッシュキー : 長音記号(「ー」) が入力される
- 全角モード、シフト+バックスラッシュキー : 全角アンダースコア文字(「_」) が入力される
全角円マークは右上にある円マークキー(刻印は「¥, |, ほ」)で入力できるので、バックスラッシュキーから全角円マークが入力できなくても問題ありません。
結果として、小指の位置をほぼ動かさずシフトキーも押さずに長音記号を入力できるようになりました。
Autohotkey
Autohotkey については、過去記事「プログラミング言語としての AutoHotKey」で書いています。Windows OS でしか使えません。プログラミング言語としてはクセが強く、どうにも歪んだ言語仕様なので、過去記事では、
プログラミング初心者がAutoHotKeyを入門や学習用に使うことはまったくおすすめできません。
と書いています。
最近では、新しいバージョン Autohotkey v2 が主流になりつつあります。Autohotkey v2 は、言語仕様がだいぶマトモになり、スクリプト言語として(ホットキー定義以外にも)使えそうです。とはいえ、スクリプト言語として積極的にオススメする気はありません。もちろん、ホットキー定義言語としては、唯一無二の優位性を持っています。
Autohotkey v2 では、ホットキー定義は次のように書けます。
キーストロークの記述::
{
任意のコード
}
つまり、キーストロークをトリガー・イベントとするイベントハンドラーの形に書けます。コードブロックは、関数の本体ブロックと変わりません。スッキリしましたね。
互換性から変な構文/変な仕様は残ってますが、できるだけ変なコードは書かないようにすれば、そこそこモダンな感じのプログラムになります。
長音記号の入力のためのホットキー定義は次のようです。
sc073:: { if (IME_GET()) { Send("ー") } else { Send("\") } }
キーのスキャンコード
Autohotkey のキーストローク記述において、[A] キーなら単に a と書くだけです。[Ctrl]+[A] ならば ^a ですね、簡単。しかし、文字「/」を発生させるキーは、バックスラッシュキーと円マークキーの2つがあります。どちらのキーが押されたかをどう区別するのだろうか?
キーが押される(そして、放される)と、KeyDown, KeyUp イベントが発生します。どのキーが押されたかはスキャンコードという番号で識別されるとのこと。Autohotkey では、"sc" のあとにスキャンコードでキーを記述できます。例えば、sc029 は無変換キーを表します。
スキャンコードを使えば異なるキーを区別できますね。それに、スキャンコードを使ったほうが確実で安心。じゃ、スキャンコードはどう調べればいいだろう? ここで僕はしくじってしまいました。以下、しくじりを時系列順で書きますが、興味がなければスキップして次の節へどうぞ。
リアルタイムに押したキーの情報を表示してくれるソフトウェアはないだろうか? 探したら次が見つかりました。
- Keymill https://kts.sakaiweb.com/keymill.html
ファイル: Keymill14.{exe|zip}
実行するために、古いバージョン(バージョン 3.5 以前)の .NET Framework が必要なのでインストールしました。思ってたとおりのソフトウェアで、「おー、これだこれだ」と。
上の画像は、バックスラッシュキーを押して、記録停止した状態の画面スナップショットです。スキャンコードが 125 だったので、次のような Autohotkey のテストコードを書いて試してみました。チルダは、キーストロークを消費せずにそのまま素通りさせることを指示します。
~sc125:: { MsgBox("Pressed!") }
アリッ? うまくいかない。 KeyMill の数値が10進数で、Autohotkey は16進数だとは気付いたのですが、それを修正してもダメ。KeyMill の「仮想キーコード」ってのが実は Autohotkey の「スキャンコード」なのでは? とか試行錯誤したのですが、うまくいかず(困惑して無為な時間を過ごす)。KeyMill の表示と Autohotkey のスキャンコードの翻訳ルールが今でもわかりません。
実はドキュメンテーションもあったし、Autohotkey 自体の機能でスキャンコードを調べることもできたのです(そりゃそうだよね)。
設定の手順
スキャンコードに関するドキュメンテーションは以下です。
AutoHotKey でキーの情報を調べるには:
- タスクトレイの AutoHotKey のアイコンをダブルクリックする。Autohotkey のコンソールウィンドウが表示される。
- メニューから View → Key history and script info を選択。
- [F5] を押すと、ウィンドウの一番下に押したキーの情報が表示される。
コンソールの VK(仮想キー)や SC(スキャンコード)の欄を見れば、Autohotkey で使えるキーストローク記述がわかります。
バックスラッシュキーのスキャンコードは sc073 だと分かるので以下のコード(再掲)で目的が達成できます。
sc073:: { if (IME_GET()) { Send("ー") } else { Send("\") } }
ここで使っている IME_GET 関数は、以下の記事からそのままコピーしました(ありがとうございます)。
上記記事からの IME_GET 関数のコードを貼り付けておきます。
;----------------------------------------------------------- ; IMEの状態の取得 ; WinTitle="A" 対象Window ; 戻り値 1:ON / 0:OFF ;----------------------------------------------------------- IME_GET(WinTitle:="A") { hwnd := WinExist(WinTitle) if (WinActive(WinTitle)) { ptrSize := !A_PtrSize ? 4 : A_PtrSize cbSize := 4+4+(PtrSize*6)+16 stGTI := Buffer(cbSize,0) NumPut("DWORD", cbSize, stGTI.Ptr,0) ; DWORD cbSize; hwnd := DllCall("GetGUIThreadInfo", "Uint",0, "Uint", stGTI.Ptr) ? NumGet(stGTI.Ptr,8+PtrSize,"Uint") : hwnd } return DllCall("SendMessage" , "UInt", DllCall("imm32\ImmGetDefaultIMEWnd", "Uint",hwnd) , "UInt", 0x0283 ;Message : WM_IME_CONTROL , "Int", 0x0005 ;wParam : IMC_GETOPENSTATUS , "Int", 0) ;lParam : 0 }
*1:文字の名前は Katakana-Hiragana Prolonged Sound Mark です