HID Macros と Autohotkey を連携させる




MagicKeyPadの後継ソフトが公開されました。(2012年8月末)

  • USBテンキー用(USBテンキー以外も可)のカスタマイズツールMagicKeyPadの(非公認)後継ソフトとしてHidKeySequence(http://hks.wktk.so/)が公開されました。
    公式サイトが閉鎖したようなので2次配布先はこちら
    作者様に感謝致します。

    MagicKeyPadの代替えの1つになればと思って作ったこのサイトですが、USBテンキー以外のHID(ヒューマンインターフェイスデバイス)でこのサイトを参考にされている方がいらっしゃるようなのでそのまま残します。


HID Macros と Autohotkey を連携させ、USBテンキーをカスタマイズする場合の例


概念

  • 2chの「CG用補助入力総合」スレにMagicKeyPadというUSBテンキーをデバイスごとにカスタマイズ出来る(※USBキーボードと同じキーコードを吐くUSBデバイスなら何でもOKなので通常のUSBキーボードやNostromo SpeedPad N52もカスタマイズ可能)超便利なソフトがうpさたので有難く使わせて頂いておりました。しかし、32bit OSまでしか対応しておらず、64bit対応が求められていましたが、様々な事情(理由の1つとして64bit対応するためにはM$にお布施が必要?)で64bit未対応です。そこでHID MacrosならMagicKeyPadの代わりになるんじゃないかというレスが同スレにあり、Autohotkeyと連携できそうだったのでこのサイトを作りました。(2011年12月)
  • HID Macrosだけではキーの押しっぱなしやキーマップ切り替え等は出来ませんが、AutoHotkeyを連携させればそれらを行うことができます。
  • HID Macrosはキーインプット(どのデバイスのどのキーを押したか)の識別のみ行い、その後の処理(キー割り当て変更等)を全てAutoHotkeyで処理するようにします。
  • 手順(1)~(7)に書いてある通りに従ってそのままやってもらうだけで連携に必要な基本設定は終わります。
    キー割り当て、アプリごとの設定、キーマップ切り替え等はAutoHotkeyで行いますので、AutoHotkeyを扱ったことがないと厳しいと思います。
    手順(8-x)にサンプルっぽいものを書いていますが、スクリプト系を全く扱ったことがないと解かりにくい(解らない)のでAutoHotkeyを触ってみていろいろ試してください。

HID MacrosとAutoHotkeyと連携させる理由

  • HID MacrosはフライトシュミレーターX用に作られたツールであり、ゲーム設定でキー押しっぱなしが設定出来るため、HID Macrosの機能として実装しないようなのでAutohotkeyでキー押しっぱなし等を出来るようにします。。
  • HID MacrosはVBScriptやJScriptが使えるのでそのスクリプトが書ければHID Mascrosだけで出来るかもしれませんが、VBScriptやJScriptが解らないので代わりにAutoHotkeyを使います。



(1) AutoHotkey と HID Macros と SFC mini をインストール

  • AutoHotkeyAutoHotkey_L)をインストール。
    ※私はAutohotkey(開発停止)を利用していますが、現在の主流はAutoHotkey_Lです(開発が本家からL版へと引き継がれた)。


  • HID Macros をインストール。

  • SFC mini をインストール。
    HID Macros(VBScript)でWinApiを簡単に利用するためにインストールします。
    VBScriptとWinApiは(1)~(7)の基本設定を行うために必要なだけで、それ以外ではVBScriptとWinApiを使う必要ありません。
    また、(1)~(7)に書いてある通りに従ってそのままやってもらうだけで連携に必要な基本設定は終わります。

(2) USBテンキー(USBデバイス)を接続する

 
USBテンキー(USBデバイス)を接続する。※(1)の前に接続していても可

<補足説明>
NumLock非連動(現在の主流?)タイプのUSBテンキーの場合、キーボードとUSBテンキーのNumLock状態が異なるとNumLockのキーコードを自動で送る仕組みになっています。
例えばキーボードがNumLock OffでUSBテンキーがNumLock Onの場合、USBテンキーの1を押すとUSBテンキーは以下のようにキーコードを発行します。
「NumLock On → テンキーの1 → NumLock Off」
逆にキーボードのNumLockがOn、USBテンキーがNumLock Offの場合、
「NumLock Off → テンキーの1 → NumLock On」
というキーコードを発行しています。
これが非連動の仕組み(仕様)です。
このようにNumLockを自動で送らせないようにするにはキーボードとUSBテンキーのNumLock状態を常に同じにしておく必要があります。
また、NumLock On と Off の状態ではテンキーのキーコードが異なるため、HID Macrosへのキー登録、及び利用時はいつも同じ状態にしておくことを推奨します。

(3) Hid Macros の設定を確認する

 
Hid Macros を起動し、Hid Macrosのウィンドウを開く。
Hid Macros の「Settings」タブの
Scritp のところにある Language を初期値(VBScript)にする。
※「General」のところにある Language ではないので注意。

(4) Hid Macros の設定 Routines

 
①Hid Macros の「Script」タブを選択する
②下記スクリプトを「Routines」にコピペする
③右下の「Compile」をクリックする
 (左下の赤丸が緑丸に変わったらOK)
Dim hWnd
Dim FindWindow
Dim PostMessage
Set FindWindow = CreateObject("SfcMini.DynaCall")
FindWindow.Declare "user32","FindWindow"
Set PostMessage = CreateObject("SfcMini.DynaCall")
PostMessage.Declare "user32","PostMessage"

(5) ahk_hidmacros.ahk を作成する

 
ahk_hidmacros.ahk を作成する。
※フォルダオプションで全ての拡張子を表示するようにしている場合の説明です。
デスクトップやフォルダの何も無いところを右クリック → 新規作成 → Autohotkey Script を選択 → 名前を ahk_hidmacros.ahk にする。
もしくは 新規作成 → テキストドキュメント を選択 → 名前を ahk_hidmacros.ahk にする。
要するに ini、xml、dat、xls 等なんでもいいので新規ファイルを作成し、名前を ahk_hidmacros.ahk にすればOKです。
次にテキストエディタで ahk_hidmacros.ahk を開き、下記21行を貼付ける(下記21行に全て置き換える)。
上書き保存する。※Autohotkey_L Unicode版で利用する場合はスクリプトファイルのファイルエンコーディングについてを参照してください。
#SingleInstance, Force
#Persistent
OnMessage(99999, "HidMacros")
Menu, Tray, Add , GetScript
return ; Autoexecセクション はここまで

GetScript: ; スクリプトをクリップボードにコピーする
    DetectHiddenWindows, On
    SetTitleMatchMode,RegEx
    Hwnd := WinExist(".*\\ahk_hidmacros.ahk\s-\sAutoHotkey.* ahk_class AutoHotkey")
    WinGetTitle, WinTitle, ahk_id %Hwnd%
    Clipboard = hWnd = FindWindow ( "AutoHotkey", `"%WinTitle%`" )
    Clipboard = %Clipboard%`nIf hWnd then`n    Call PostMessage(hWnd, 99999, 1, 1 )
    Clipboard = %Clipboard%`nEnd If
    msgbox, %Clipboard%`nをクリップボードにコピーしました。
    DetectHiddenWindows, Off
return

HidMacros(wParam, lParam) {
    msgbox, ahk_hidmacros.ahkのテストです`nwParam = %wParam%`nlParam = %lParam%
}

Autoexecセクションに記述した OnMessage(99999, "HidMacros") はHID Macrosからのメッセージを受け取る重要な部分です。
OnMessageの第1引数 99999 を16進数にするとHidmacrosとahkで値が異なる場合(処理の違い)があるので特に問題や拘りがなければ 99999 のままにしておいてください。
OnMessageの第2引数("HidMacros" の部分)はファンクション名なので好きな名称でOKです(ファンクション名は半角のみが有効であり、全角は使用不可です。また頭文字はアルファベットでなければなりません。2文字目以降は数字や _ アンダーバーが使えます)。但し、ファンクション名を変更する場合、手順(9-1)以降のファンクション名(関数名)を書き換え、統一してください。よく分からない場合は HidMacros のままにしておいてください。

(6) ahk_hidmacros.ahk を実行し、スクリプトを取得する

 
①手順(5)で作成した ahk_hidmacros.ahk を実行(ダブルクリック)する。
②タスクトレイにアイコン(緑の背景に H マークのアイコン)があるはずなので右クリックする。
③「GetScript」を選択(クリック)してください。
これで手順(7-1)で必要なVBスクリプトがクリップボードにコピーされました。
クリップボードにコピーされたものは下記と同じはずです("AutoHotkeyスクリプトのウィンドウタイトル"部分は環境によって異なります。)
hWnd = FindWindow ( "AutoHotkey","AutoHotkeyスクリプトのウィンドウタイトル" )
If hWnd then
    Call PostMessage(hWnd, 99999, 1, 1 )
End If

(7) Hid Macros のキー毎の設定 その1

  • ペイントツールSAI用に設定する場合はこちらを参照してください。

 
「どのUSBデバイスのどのキーを押したのか」という情報をAutoHotkey(ahk_hidmacros.ahk)へ伝える命令を登録します。

①「Macros」タブを選択
②「New」をクリック
③好きな名称(自分で判りやすい名称)を付ける。 例 Tenkey1
 ※名称を変更せず「New Macro」のままでも問題はありません。
④Edit Macroのところにある「Scan」をクリック
⑤USBテンキーの1キー(または他のキー)を押す
⑥Action のところの「Scripted」を選択する
⑦手順(6)で取得したVBスクリプトを貼り付ける
⑧右下の「Compile」をクリック(赤丸から緑丸になればOK)
⑨手順⑤で押したキーを押し、メッセージボックスに「ahk_hidmacros.ahkのテストです」と表示されるのを確認する。
 ※メッセージが表示されない場合はここまでの手順のどこかで間違っている可能性が高いです。
⑩メッセージが表示されるのを確認できたら下記表を参考に①~⑨を繰り返し、USBテンキーのキーを全て追加(登録)する。
※"AutoHotkeyスクリプトのウィンドウタイトル"部分は環境によって異なります。
※数値の入力は半角のみOKです。全角はダメです。
hWnd = FindWindow ( "AutoHotkey", "AutoHotkeyスクリプトのウィンドウタイトル" )
If hWnd then
    Call PostMessage(hWnd, 99999, 1, 2) ' それぞれに応じて第四引数(lParam)を編集する。
End If
USBテンキー
のキー
wParam
(第3引数)
lParam
(第4引数)
PostMessage(hWnd, msg, wParam, lParam)
1 1 1 PostMessage(hWnd, 99999, 1, 1)
2 2 PostMessage(hWnd, 99999, 1, 2)
3 3 PostMessage(hWnd, 99999, 1, 3)
4 4 PostMessage(hWnd, 99999, 1, 4)
5 5 PostMessage(hWnd, 99999, 1, 5)
6 6 PostMessage(hWnd, 99999, 1, 6)
7 7 PostMessage(hWnd, 99999, 1, 7)
8 8 PostMessage(hWnd, 99999, 1, 8)
9 9 PostMessage(hWnd, 99999, 1, 9)
0 10 PostMessage(hWnd, 99999, 1, 10)
.(ドット) 11 PostMessage(hWnd, 99999, 1, 11)
Tab 12 PostMessage(hWnd, 99999, 1, 12)
/ 13 PostMessage(hWnd, 99999, 1, 13)
* 14 PostMessage(hWnd, 99999, 1, 14)
BackSpace 15 PostMessage(hWnd, 99999, 1, 15)
- 16 PostMessage(hWnd, 99999, 1, 16)
+ 17 PostMessage(hWnd, 99999, 1, 17)
Enter 18 PostMessage(hWnd, 99999, 1, 18)

ここで少し解説。
PostMessage の引数について(※このPostMessageを使ってAutoHotkeyに伝えています)
※引数に利用する変数(変数名)や数値の入力は半角のみOKです。全角はダメです。
第一引数は hWnd = メッセージの送り先のハンドルウィンドウ(ID)を指定します。
  ここでは hWnd のままでOKです。(hWndという変数にIDを代入している)
第二引数は msg = ウィンドウメッセージ番号であり、送信側と受信側で同じ番号を指定します。
  ここでは 99999 で固定しています。
第三引数は wParam = メッセージ引数。ここではUSBデバイスを判別させるために利用しています。
※USBテンキーなら wParam = 1 (第三引数を 1 )ということにします。
※wParam = 1 にしていますが、値は 0~4294967295 の整数なら何でもOKです。
※USBテンキーを複数利用する場合、2台目を wParam = 2 、3台目を wParam = 3 というようにすると分り易いと思います。
第四引数は lParam = メッセージ引数。ここでは押したキーを判別させるために利用しています。



基本設定はここまでです。これ以降はAutoHotkeyを扱えることが前提となります。



(8-0-1) このページ内のAutohotkey スクリプトサンプルについて

  • Autohotkey サンプル」等の検索キーワードで訪れた方に補足しますが、このページ内のサンプルはAutohotkeyを使った通常のキーカスタマイズ方法ではなく、HID Macrosと連携させることを前提にしたサンプルを掲載しています。よって下記のような基本的なキーカスタマイズの解説やサンプルはありませんのでご注意を。
a::b ; a を b にリマップする(置き換える)
a::send,b ; a を押したら b を送る

(8-0-2) スクリプトファイルのファイルエンコーディングについて

  • アップロードしているスクリプトサンプルは全てShift JIS形式で保存しています。
    よって、そのままだとAutohotkey_L Unicode版(以後、L版)で動作しません。
    L版で利用するにはスクリプトサンプル(ahk_hidmacros.ahk)をテキストエディタ(NotePad等)で開き、 UTF-8 形式で保存(上書き保存)してから利用してください。
    参考サイト:テキストをUTF-8形式で保存する。



(8-1) キー割り当てを設定するスクリプトのサンプル

 
+←サンプルを表示する
#SingleInstance, Force
#Persistent
OnMessage(99999, "HidMacros")
Menu, Tray, Add , GetScript
return ; Autoexecセクション はここまで

GetScript: ; スクリプトをクリップボードにコピーする
    DetectHiddenWindows, On
    SetTitleMatchMode,RegEx
    Hwnd := WinExist(".*\\ahk_hidmacros.ahk\s-\sAutoHotkey.* ahk_class AutoHotkey")
    WinGetTitle, WinTitle, ahk_id %Hwnd%
    Clipboard = hWnd = FindWindow ( "AutoHotkey", `"%WinTitle%`" )
    Clipboard = %Clipboard%`nIf hWnd then`n    Call PostMessage(hWnd, 99999, 1, 1 )
    Clipboard = %Clipboard%`nEnd If
    msgbox, %Clipboard%`nをクリップボードにコピーしました。
    DetectHiddenWindows, Off
return

; HidMacros( [wParam, lParam, msg, hwnd] ) 引数は省略可
HidMacros(wParam, lParam) { ; 第三と第四引数は必要ないので省く。
    If ( lParam = 1 ) { ; テンキー1 なら
        send, {space down} ; spaceを押し下げる ※Saiなら手のひらツール
        keywait, Numpad1 ; テンキーの1を開放するまで待つ
        send, {space up} ; spaceを放す
    } Else If ( lParam = 2 ) { ; テンキー2 なら
        send, {alt down} ; Altを押し下げる ※Saiならスポイト
        keywait, Numpad2 ; テンキーの2を開放するまで待つ
        send, {alt up} ; Altを放す
    } Else If ( lParam = 3 ) { ; テンキー3 なら
        send, {alt down}{space down} ; AltとSpaceを押し下げる ※Saiならビュー回転
        keywait, Numpad3 ; テンキーの3を開放するまで待つ
        send, {space Up}{alt up} ; AltとSpaceを放す
    }
}

このサンプルをDownloadする
(ファイル名やディレクトリがHID Macrosで設定したものと異なると動作(連携)しません。元ファイルを上書きコピーするか、中身だけを元の ahk_hidmacros.ahk にコピペして実行してください。Autohotkey_L Unicode版で利用する場合はスクリプトファイルのファイルエンコーディングについてを参照してください。)

ahk_hidmacros.ahk の Autoexecセクション以外(以降)に wParam 及び lParam の値ごと(デバイスとキーごと)に分岐させるスクリプトを記述してください。
ahk_hidmacros.ahk(スクリプト)の編集が終わったら上書き保存し、ahk_hidmacros.ahk を再実行してください。
AutoHotkeyで使うキーリスト


(8-2) USBデバイスごとに設定(分岐)するスクリプトのサンプル

 
+←サンプルを表示する
;この最初の部分は手順(5)と同一なので省略します

HidMacros(wParam, lParam) {
    If ( wParam = 1 ) { ; USBテンキーAなら
        If ( lParam = 1 ) { ; USBテンキーAの 1 なら
            send, {space down} ; spaceを押し下げる ※Saiなら手のひらツール
            keywait, Numpad1 ; テンキーの1を開放するまで待つ
            send, {space up} ; spaceを放す
        } Else If ( lParam = 2 ) { ; USBテンキーAの 2 なら
            send, {alt down} ; Altを押し下げる ※Saiならスポイト
            keywait, Numpad2 ; テンキーの2を開放するまで待つ
            send, {alt up} ; Altを放す
        } Else If ( lParam = 3 ) { ; USBテンキーAの 3 なら
            send, {alt down}{space down} ; AltとSpaceを押し下げる ※Saiならビュー回転
            keywait, Numpad3 ; テンキーの3を開放するまで待つ
            send, {space Up}{alt up} ; AltとSpaceを放す
        }
    } Else If ( wParam = 2 ) { ; USBテンキーBなら
        If ( lParam = 1 ) { ; USBテンキーBの 1 なら
            send, {a} ; a を押す(クリック)
        } Else If ( lParam = 2 ) { ; USBテンキーBの 2 なら
            send, {b} ; b を押す(クリック)
        } Else If ( lParam = 3 ) { ; USBテンキーBの 3 なら
            send, {c} ; c を押す(クリック)
        }
    }
}

このサンプルをDownloadする
(ファイル名やディレクトリがHID Macrosで設定したものと異なると動作(連携)しません。元ファイルを上書きコピーするか、中身だけを元の ahk_hidmacros.ahk にコピペして実行してください。Autohotkey_L Unicode版で利用する場合はスクリプトファイルのファイルエンコーディングについてを参照してください。)

(8-1)に新たな条件「wParam = 1 なら (USBテンキーAなら)」と「wParam = 2 なら (USBテンキーBなら)」を追加しています。
ahk_hidmacros.ahk(スクリプト)の編集が終わったら上書き保存し、ahk_hidmacros.ahk を再実行してください。
AutoHotkeyで使うキーリスト


(8-3) アプリ毎に設定(分岐)するスクリプトのサンプル その1

 
+←サンプルを表示する
;この最初の部分は手順(5)と同一なので省略します

HidMacros(wParam, lParam) {
    IfWinActive, ahk_class sfl_window_class ; Saiがアクティブなら
    {
        If ( wParam = 1 ) { ; USBテンキーなら
            If ( lParam = 1 ) { ; テンキー1 なら
                send, {space down} ; spaceを押し下げる ※Saiなら手のひらツール
                keywait, Numpad1 ; テンキーの1を開放するまで待つ
                send, {space up} ; spaceを放す
            } Else If ( lParam = 2 ) { ; テンキー2 なら
                send, {alt down} ; Altを押し下げる ※Saiならスポイト
                keywait, Numpad2 ; テンキーの2を開放するまで待つ
                send, {alt up} ; Altを放す
            } Else If ( lParam = 3 ) { ; テンキー3 なら
                send, {alt down}{space down} ; AltとSpaceを押し下げる ※Saiならビュー回転
                keywait, Numpad3 ; テンキーの3を開放するまで待つ
                send, {space Up}{alt up} ; AltとSpaceを放す
            }
        }
    } Else { ; Saiが非アクティブなら
        If ( wParam = 1 ) { ; USBテンキーなら
            If ( lParam = 1 ) { ; テンキー1 を a にする
                send, {a}
            } Else If ( lParam = 2 ) { ; テンキー2 を b にする
                send, {b}
            } Else If ( lParam = 3 ) { ; テンキー3 を c にする
                send, {c}
            }
        }
    }
}

このサンプルをDownloadする
(ファイル名やディレクトリがHID Macrosで設定したものと異なると動作(連携)しません。元ファイルを上書きコピーするか、中身だけを元の ahk_hidmacros.ahk にコピペして実行してください。Autohotkey_L Unicode版で利用する場合はスクリプトファイルのファイルエンコーディングについてを参照してください。)

(8-2)に新たな条件「Saiがアクティブなら」を追加する。
IfWinActive, ahk_class sfl_window_class
  • IfWinActive等で使うウィンドウタイトルやウィンドウクラスの取得は基本的に AU3_Spy.exe(Autohotkey本家に同梱されており、本家をインストール済ならAutohotkey.exeと同じフォルダにあります)を使えば簡単に取得できます。
    AU3_Spy.exe を実行し、調べたいウィンドウをクリック(アクティブに)するだけです。
ahk_hidmacros.ahk(スクリプト)の編集が終わったら上書き保存し、ahk_hidmacros.ahk を再実行してください。
AutoHotkeyで使うキーリスト


(8-4) アプリ毎に設定(分岐)するスクリプトのサンプル その2

 
+←サンプルを表示する
;この最初の部分は手順(5)と同一なので省略します

HidMacros(wParam, lParam) {
    If ( wParam = 1 ) { ; USBテンキーなら
        IfWinActive, ahk_class sfl_window_class ; Saiがアクティブなら
        {
            If ( lParam = 1 ) { ; テンキー1 なら
                send, {space down} ; spaceを押し下げる ※Saiなら手のひらツール
                keywait, Numpad1 ; テンキーの1を開放するまで待つ
                send, {space up} ; spaceを放す
            } Else If ( lParam = 2 ) { ; テンキー2 なら
                send, {alt down} ; Altを押し下げる ※Saiならスポイト
                keywait, Numpad2 ; テンキーの2を開放するまで待つ
                send, {alt up} ; Altを放す
            } Else If ( lParam = 3 ) { ; テンキー3 なら
                send, {alt down}{space down} ; AltとSpaceを押し下げる ※Saiならビュー回転
                keywait, Numpad3 ; テンキーの3を開放するまで待つ
                send, {space Up}{alt up} ; AltとSpaceを放す
            }
        } Else { ; Saiが非アクティブなら
            If ( wParam = 1 ) { ; USBテンキーなら
                If ( lParam = 1 ) { ; テンキー1 なら
                    send, {a} ; A をクリック(押して放す)
                } Else If ( lParam = 2 ) { ; テンキー2 なら
                    send, {b} ; B をクリック(押して放す)
                } Else If ( lParam = 3 ) { ; テンキー3 なら
                    send, {c} ; C をクリック(押して放す)
                }
            }
        }
    }
}

このサンプルをDownloadする
(ファイル名やディレクトリがHID Macrosで設定したものと異なると動作(連携)しません。元ファイルを上書きコピーするか、中身だけを元の ahk_hidmacros.ahk にコピペして実行してください。Autohotkey_L Unicode版で利用する場合はスクリプトファイルのファイルエンコーディングについてを参照してください。)

条件「Saiがアクティブなら」を追加しています。
IfWinActive, ahk_class sfl_window_class
ahk_hidmacros.ahk(スクリプト)の編集が終わったら上書き保存し、ahk_hidmacros.ahk を再実行してください。
AutoHotkeyで使うキーリスト


(8-5) キーの押しっぱなし部分を関数化し、追加や編集を簡単にするサンプル

 
+←サンプルを表示する
;この最初の部分は手順(5)と同一なので省略します

HidMacros(wParam, lParam) {
    If ( lParam = 1 ) { ; テンキー1 なら
        HoldDownKey("Numpad1", "space") ; テンキーの1を押している間は space を押したままに
    } Else If ( lParam = 2 ) { ; テンキー2 なら
        HoldDownKey("Numpad2", "alt") ; テンキーの2を押している間は Alt 押したままに
    } Else If ( lParam = 3 ) { ; テンキー3 なら
        HoldDownKey("Numpad3", "alt", "space") ; テンキーの3を押している間は Alt+Space を押したままに
    }
}

HoldDownKey(waitkey, key1, key2="", key3="", key4="") {
    send, {%key1% down}
;   ここでのTrue(1)はキーが代入されているか否かです。代入されていなければ False(0) となります。
    send, % key2 ? "{" key2 " down}" : ; key2 がTrueなら仮想キー key2 を押し下げ
    send, % key3 ? "{" key3 " down}" : ; key3 がTrueなら仮想キー key3 を押し下げ
    send, % key4 ? "{" key4 " down}" : ; key4 がTrueなら仮想キー key4 を押し下げ
    keywait, %waitkey%
    send, % key4 ? "{" key4 " up}" : ; key4 がTrueなら仮想キー key4 を放す
    send, % key3 ? "{" key3 " up}" : ; key3 がTrueなら仮想キー key3 を放す
    send, % key2 ? "{" key2 " up}" : ; key2 がTrueなら仮想キー key2 を放す
    send, {%key1% up}
}

このサンプルをDownloadする
(ファイル名やディレクトリがHID Macrosで設定したものと異なると動作(連携)しません。元ファイルを上書きコピーするか、中身だけを元の ahk_hidmacros.ahk にコピペして実行してください。Autohotkey_L Unicode版で利用する場合はスクリプトファイルのファイルエンコーディングについてを参照してください。)

(8-1)のキー押しっぱなしにする部分を関数化した例です。
基本的にアプリケーションソフトのショートカットキーは4キー同時押しまで(Shit+Ctrl+Alt+A 等)なので、同時押し4キーまでを関数化した場合の例です。
HoldDownKey(実際に押しているキー, 仮想キー1, 仮想キー2, 仮想キー3, 仮想キー4)
※仮想キー2(第3引数)以降は省略可
仮想キー1,2,3,4の順序でキーを押し下げ(Down)、逆順の4,3,2,1でキーを放します(Up)。
仮想キーと書いていますが、割り当てたキーと置き換えてください。
このように関数化してしまえば3行が1行で済みますので追加や変更が簡単にできます。
ahk_hidmacros.ahk(スクリプト)の編集が終わったら上書き保存し、ahk_hidmacros.ahk を再実行してください。
AutoHotkeyで使うキーリスト

ちなみに
send, % key2 ? "{" key2 " down}" :
If key2
    send, {%key2% down}
は書き方(三項演算子とIf文)が違いますが同じ動作をします。

(8-6) キーマップを切り替えるサンプル

 
+←サンプルを表示する
;この最初の部分は手順(5)と同一なので省略します

HidMacros(wParam, lParam) {
    global keymap ; 変数 keymap をグローバル変数にする
    keymap = % !keymap ? 1 : keymap ; keymap が ""(空)なら keymap = 1 にする
    If ( lParam = 12 ) { ; USBテンキーのTabなら
        keymap = % keymap > 2 ? 1 : keymap + 1 ; 2より大きいなら1にし、それ以外は keymap+1 とする。
        keywait, Tab ; USBテンキーのTabを開放するまで待つ ※keymapが一気に2つ変化しないようにする
        return
    }
    If ( keymap = 1 ) { ; キーマップが 1 なら
        If ( lParam = 1 ) { ; USBテンキー1 なら
            HoldDownKey("Numpad1", "space") ; USBテンキーの1を押している間は space を押したままに
        } Else If ( lParam = 2 ) { ; USBテンキー2 なら
            HoldDownKey("Numpad2", "alt") ; USBテンキーの2を押している間は Alt 押したまま
        } Else If ( lParam = 3 ) { ; USBテンキー3 なら
            HoldDownKey("Numpad3", "alt", "space") ; USBテンキーの3を押している間は Alt+Space を押したままに
        }
    } Else If ( keymap = 2 ) { ; キーマップが 2 なら
        If ( lParam = 1 ) { ; USBテンキー1 なら
            HoldDownKey("Numpad1", "ctrl") ; USBテンキーの1を押している間は Ctrl
        } Else If ( lParam = 2 ) { ; USBテンキー2 なら
            HoldDownKey("Numpad2", "ctrl", "alt") ; USBテンキーの2を押している間は Ctrl+Alt
        } Else If ( lParam = 3 ) { ; USBテンキー3 なら
            HoldDownKey("Numpad3", "ctrl", "alt", "space") ; USBテンキーの3を押している間は Ctrl+Alt+Space
        }
    } Else If ( keymap = 3 ) { ; キーマップが 3 なら
        If ( lParam = 1 ) { ; USBテンキー1 なら
            HoldDownKey("Numpad1", "alt") ; USBテンキーの1を押している間は Alt
        } Else If ( lParam = 2 ) { ; USBテンキー2 なら
            HoldDownKey("Numpad2", "space") ; USBテンキーの2を押している間は Space
        } Else If ( lParam = 3 ) { ; USBテンキー3 なら
            HoldDownKey("Numpad3", "space") ; USBテンキーの3を押している間は Space
        }
    }
}

HoldDownKey(waitkey, key1, key2="", key3="", key4="") {
    send, {%key1% down}
    send, % key2 ? "{" key2 " down}" : ; key2 がTrueなら仮想キー key2 を押し下げ
    send, % key3 ? "{" key3 " down}" : ; key3 がTrueなら仮想キー key3 を押し下げ
    send, % key4 ? "{" key4 " down}" : ; key4 がTrueなら仮想キー key4 を押し下げ
    keywait, %waitkey%
    send, % key4 ? "{" key4 " up}" : ; key4 がTrueなら仮想キー key4 を放す
    send, % key3 ? "{" key3 " up}" : ; key3 がTrueなら仮想キー key3 を放す
    send, % key2 ? "{" key2 " up}" : ; key2 がTrueなら仮想キー key2 を放す
    send, {%key1% up}
}

このサンプルをDownloadする
(ファイル名やディレクトリがHID Macrosで設定したものと異なると動作(連携)しません。元ファイルを上書きコピーするか、中身だけを元の ahk_hidmacros.ahk にコピペして実行してください。Autohotkey_L Unicode版で利用する場合はスクリプトファイルのファイルエンコーディングについてを参照してください。)

(8-5)をベースにキーマップ切り替えを加えた例です。
USBテンキーのTabキー ( lParam = 12 ) でキーマップ(1,2,3)を切り替えるようにします。

(8-7)キーの同時押し(0キーを押しながら1キー等)に割り当てるサンプル

 
+←サンプルを表示する
#SingleInstance, Force
#Persistent
OnMessage(99999, "HidMacros")
Menu, Tray, Add , GetScript
settimer, keycheck, 50 ; キー押し下げ/開放を keycheck で 50ms 間隔で調べる
tkey1 = Numpad1
tkey2 = Numpad2
tkey3 = Numpad3
tkey4 = Numpad4
tkey5 = Numpad5
tkey6 = Numpad6
tkey7 = Numpad7
tkey8 = Numpad8
tkey9 = Numpad9
tkey10 = Numpad0
tkey11 = Numpaddot
tkey12 = Tab
tkey13 = NumpadDiv
tkey14 = NumpadMult
tkey15 = Bs
tkey16 = Numpadsub
tkey17 = Numpadadd
tkey18 = NumpadEnter
;ChangekeyでテンキーをF13~F24置き換えた場合は場合は↓のtkey1~tkey18の行頭のセミコロン(;)を削除して使う。
;tkey1 = F13
;tkey2 = F14
;tkey3 = F15
;tkey4 = F16
;tkey5 = Numpad5
;tkey6 = F17
;tkey7 = F18
;tkey8 = F19
;tkey9 = F20
;tkey10 = F21
;tkey11 = F22
;tkey12 = tab
;tkey13 = NumpadDiv
;tkey14 = NumpadMult
;tkey15 = Bs
;tkey16 = F23
;tkey17 = F24
;tkey18 = NumpadEnter
return ; Autoexecセクション はここまで

esc::exitapp ; Escキーでスクリプトを終了させる。 ループから抜けられなくなったとき用。

GetScript: ; スクリプトをクリップボードにコピーする
    DetectHiddenWindows, On
    SetTitleMatchMode,RegEx
    Hwnd := WinExist(".*\\ahk_hidmacros.ahk\s-\sAutoHotkey.* ahk_class AutoHotkey")
    WinGetTitle, WinTitle, ahk_id %Hwnd%
    Clipboard = hWnd = FindWindow ( "AutoHotkey", `"%WinTitle%`" )
    Clipboard = %Clipboard%`nIf hWnd then`n    Call PostMessage(hWnd, 99999, 1, 1 )
    Clipboard = %Clipboard%`nEnd If
    msgbox, %Clipboard%`nをクリップボードにコピーしました。
    DetectHiddenWindows, Off
return

HidMacros(wParam, lParam) { ; 第三と第四引数は必要ないので省く。
    global tkey1, tkey2, tkey3, tkey4, tkey5, tkey6, tkey7, tkey8, tkey9, tkey10
    global tkey11, tkey12, tkey13, tkey14, tkey15, tkey16, tkey17, tkey18
    global tkey1down, tkey2down, tkey3down, tkey4down, tkey5down, tkey6down
    global tkey7down, tkey8down, tkey9down, tkey10down, tkey11down, tkey12down
    global tkey13down, tkey14down, tkey15down, tkey16down, tkey17down, tkey18down
;   キーが押されたら代入する。テンキー1(tkey1)が押されたら tkey1 を tkey1down に代入する
    loop, 18
	If ( lParam = A_Index ) {
           tkey%A_Index%down := tkey%A_Index%
           break
       }
}

keycheck:
    IfWinActive, ahk_class sfl_window_class ; Saiがアクティブなら
    {
        If ( tkey1down ) { ; 1キーが押されているなら
            If !tkey10down ; 0キーが押されていなければ
                tkey1down := HoldDownKey2(tkey1down, "space")
            Else ; 0キーが押されているなら
                tkey1down := HoldDownKey2(tkey1down, "ctrl", "space")
        }
        If ( tkey2down ) { ; 2キーが押されているなら
            If !tkey10down ; 0キーが押されていなければ
                tkey2down := HoldDownKey2(tkey2down, "alt")
            Else ; 0キーが押されているなら
                tkey2down := HoldDownKey2(tkey2down, "ctrl", "alt", "space")
        }
        If ( tkey3down ) { ; 3キーが押されているなら
            If !tkey10down ; 0キーが押されていなければ
                tkey3down := HoldDownKey2(tkey3down, "ctrl")
            Else ; 0キーが押されているなら
                tkey3down := HoldDownKey2(tkey3down, "ctrl", "alt")
        }
        If ( tkey4down ) ; 4キーが押されているなら
            tkey4down := HoldDownKey2(tkey4down, "shift")
        If ( tkey5down ) ; 5キーが押されているなら
            tkey5down := HoldDownKey2(tkey5down, "alt", "space")
        If ( tkey10down ) ; 0キー ※コンビネーションキーの起点とする。
            tkey10down := HoldDownKey2(tkey10down, "") 
;       割り当てていないキーを通常のテンキーにする。
        If ( tkey6down || tkey7down || tkey8down || tkey9down || tkey11down || tkey12down
            || tkey13down || tkey14down || tkey15down || tkey16down || tkey17down || tkey18down )
            gosub, TenkeyMode
    } Else { ; Sai以外なら通常のテンキーにする。
        gosub, TenkeyMode
    }
return

HoldDownKey2(tkeydown, vkey1="", vkey2="", vkey3="", vkey4="") {
    keywait, %tkeydown%, T0.01
    if ( vkey1 ) {
        If !errorlevel {
            send, {%vkey1% up}
            send, % vkey2 ? "{" vkey2 " up}" :
            send, % vkey3 ? "{" vkey3 " up}" :
            send, % vkey4 ? "{" vkey4 " up}" :
            return 0
        }
        If ( !getkeystate(vkey) ) {
            send, {%vkey1% down}
            send, % vkey2 ? "{" vkey2 " down}" :
            send, % vkey3 ? "{" vkey3 " down}" :
            send, % vkey4 ? "{" vkey4 " down}" :
        }
        return %tkeydown%
    } Else {
        return % errorlevel ? tkeydown : 0 ; キーが開放されたら 0 を返す
    }
}

TenkeyMode: ; 通常のテンキーにする
    tenkeys = %tkey1%|%tkey2%|%tkey3%|%tkey4%|%tkey5%|%tkey6%|%tkey7%|%tkey8%|%tkey9%|%tkey10%
    tenkeys = %tenkeys%|%tkey11%|%tkey12%|%tkey13%|%tkey14%|%tkey15%|%tkey16%|%tkey17%|%tkey18%
    Loop, Parse, tenkeys, |
    {
        If tkey%A_Index%down
        {
            send, {%A_LoopField%}
            tkey%A_Index%down = 0
        }
    }
return

このサンプルをDownloadする
(ファイル名やディレクトリがHID Macrosで設定したものと異なると動作(連携)しません。元ファイルを上書きコピーするか、中身だけを元の ahk_hidmacros.ahk にコピペして実行してください。Autohotkey_L Unicode版で利用する場合はスクリプトファイルのファイルエンコーディングについてを参照してください。)

SAIではAltキーを割り当てたキーから押すと反応しません。例えば、0キーにAlt、1キーにSpaceを割り当てた場合、0を押しながら1を押してもAltしか押されていないと判定(Saiの右下ではAlt+anyと表示)されますが、先に1キーを押しながら0キーを押すとビュー回転(Alt+Space)と判定されます。SAIでAltキーを割り当てる場合は注意してください。
私はAHK_L版(現在の主流)ではなく、ノーマル版を使っているのでこのようなスクリプトになっていますが、AHK_L版を使ったほうがもっとスマートに書けると思います(L版の #IF や 配列変数 を使うともっと簡単だと思います)。

注意点:下記の部分は同じ変数にしてください。
        ↓これ
        If ( tkey4down ) ; 4キーが押されているなら
            tkey4down := HoldDownKey2(tkey4down, "shift")
        ↑これ            ↑これ
例えば、下記の箇所が違うと5キーに割り当てたキーが押されっぱなしになる可能性が高いです。※スクリプトによって異なります。
        If ( tkey4down ) ; 4キーが押されているなら
            tkey5down := HoldDownKey2(tkey4down, "shift")
        ↑ここだけ違う
例えば、下記の箇所が違うとShiftキーが押しっぱなしになる可能性が高いです。※スクリプトによって異なります。
        If ( tkey4down ) ; 4キーが押されているなら
            tkey4down := HoldDownKey2(tkey5down, "shift")
                       ↑ここだけ違う


(9-1) USBテンキーのEnterキーが NumpadEnter or Enter のどちらなのかを調べる

 
  • テンキーのEnterについてですが、USBテンキーによっては NumpadEnter ではなく Enter の信号を送ってくるタイプがあります。
    どちらを送っているか調べるにはEnterKeyCheck.ahkをダウンロードし、実行してからUSBテンキーのEnterキーを押して調べてください。
    調べる際はHID Macrosを終了してから行なってください。
    HID Macrosを終了してから行わないとキー情報を取得出来ない場合があるからです。
    Autohotkey_L Unicode版で利用する場合はスクリプトファイルのファイルエンコーディングについてを参照してください。


更新履歴など






  • 2011-12-15 (2011-12-12を一部修正)
    • SAIがAutohotkeyよりもLowレベル(OSに近い部分)でキーを認識する問題ですが、私の実力ではAutoHotkeyだけでの回避は無理です。
      SAIはShift+Numpad系(テンキー)にビュー系のショートカットが割り当てられているため、テンキーにShiftの長押し(押しっぱなし)を割り当てるとビュー系ショートカットとして認識されてしまいます。
      回避策としては長押し(押しっぱなし)にShiftを割り当てないようにするか、面倒ですがChangeKeyを使い、テンキー(Numpad0~4、Numad6~9、NumpadAdd = +、NumpadSub = -)をF13~F24へ変更し、AutoHotkeyでF13~F24に対して割り当てを行えば誤動作しなくなります。
      (Numpad5、NumpadMult = *、NumpadDiv = / はSAI内部でショートカットが割り当てられていないので変更せずにそのまま利用してOK)
      F13~F24へ変更する方法はテンキーをF13~F24にするを参考にしてください。
      SAI(及び、割り当てを変更するアプリケーションソフト)以外はAutoHotkeyのRemapでF13~F24をテンキーにする(戻す)、もしくはここのスクリプトでF13~F24にテンキーを割り当てれば通常使いには問題が無いはずです。
    • SAI以外(PhotoShopやIllustrator等)では正常に動作しますので上記の処置を施す必要はありません。