Windowsで英字配列のApple Wireless KeyboardをMac風キーバインドにする



[Apple Wireless Keyboard](http://www.apple.com/jp/shop/product/MLA22J/A/magic-keyboard-jis)が好きでWindowsでもApple Wireless KeyboardでMac風のキーバインドで使うために色々ツールを導入したのでその時の個人的なメモ。

## 環境

- Windows 8.1 64bit
- Apple Wiress Keyboard (US) MC184LL/B

## やりたいこと

- 英字配列のApple Wireless KeyboardでWindowsでMac風のキーバインドにする
- FnキーをCtrlキーに変更
- CommandキーでIMEのOn/Off切り替え(Toggle)
- Command+Tabでウィンドウの切り替え
- Caps LockキーをCtrlキーに切り替え

## 使ったツール

- [WinA1314](https://github.com/samartzidis/WinA1314.git)
- [AutoHotKey](https://autohotkey.com/)

##  事前準備

レジストリをいじる

- `Win+R`かファイル名を指定して実行で`regedit`を入力してレジストリエディタを起動

- `HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\i8042prt\Parameters`を開く

- `LayerDriver JPN`の値を`kbd101.dll`に変更

参考: [Apple Wireless Keyboard トラブル＆Tips | Suinasia](http://suin.asia/2008/12/29/apple-wireless-keyboard-tips-1.html)

## [WinA1314](https://github.com/samartzidis/WinA1314.git)

FnキーとCtrlキーの入れ替え、CmdキーとAltキーの入れ替え等が出来る。
[Github](https://github.com/samartzidis/WinA1314.git) からダウンロードしたら`Binaries`フォルダ内に`WinA1314 Setup.exe`があるのでインストールウィザードに従ってキーバインドの変更をする。今回はFnキーとCtrlキーの入れ替えのみ実行した。CmdキーはCtrlとしてバインドされるのでCmd + C、Cmd + V等のMac風のキーバインドはそのまま実行出来る。

## [AutoHotKey](https://autohotkey.com/)

メインになるautohotkeyのスクリプトを作成する。

`apple_keyboard.ahk`

```
#Include ./IME.ahk

; Ctrl + TabでAlt + Tabを再現(※要EnableUIAccess.ahk)
LControl & Tab::AltTab ; AltTab Emulation

; ショートカット
^+]::Send ^{Tab} ; Ctrl + Tab
^+[::Send ^+{Tab} ; Ctrl + Shift + Tab
^+v::Send +{Insert} ; Insert
^q::WinClose, A ; Quit Window like Cmd + Q
^Backspace::Send {Delete} ; Send Delete
^+Backspace::Send +{Delete} ; Send Delete completely

; キー交換
RAlt::RCtrl ; Swap Right Alt key with Right Ctrl key
RCtrl::RWin ; Swap Right Ctrl key with Right Windows key
Capslock::Ctrl ; Swap capslock with Ctrl key

; CmdキーでIMEのOn/OffをToggle
Ctrl::
getIMEMode := IME_Get()  
if (%getIMEMode% = 0)  
{  
    IME_SET(1)  
    return  
}  
else
{  
    IME_SET(0)  
    return  
}
```

Windows 8では`AltTab`がセキュリティの関係上デフォルトでは使えないので [こちら](https://dl.dropbox.com/u/20532918/EnableUIAccess.zip) から`EnableUIAccess.ahk`をダウンロードし`#Include ./EnableUIAccess.ahk`という行をスクリプトに追記してからスクリプトを起動しAutoHotKey.exeを署名済みの`.exe`ファイルに置き換える。一度exeファイルを上書きしたら以降はIncludeは削除して問題ない。

参考: [Enable interaction with administrative programs](https://autohotkey.com/board/topic/70449-enable-interaction-with-administrative-programs/)

また事前に[IME.ahk](http://lukewarm.s101.xrea.com/up/file/089.zip)をダウンロードしておく。（リンク先zipフォルダ内`lib/IME.ahk`をコピー。リンク切れの場合は以下のコードをコピペして`apple_keyboard.ahk`と同じフォルダに入れておく）

`IME.ahk`

```
/*----------------------------------------------------------------------------
  IME 制御用 Functuion (コピペ用)
   動作確認環境  2005/09/12
     WinNT4 SP6 / WinXP SP2 (98系でもおそらくはOK)

    IME_Func.ahk からよく使う IME状態取得/セット部のみ抽出
    各関数間に依存関係はありません。
    関数間の依存関係は無いので
    必要な関数単体で

    2008.07.11 v1.0.47以降の 関数ライブラリスクリプト対応用にファイル名を修正
-----------------------------------------------------------------------------
*/


IME_GET(WinTitle="")
;-----------------------------------------------------------
; IMEの状態の取得
;    対象： AHK v1.0.34以降
;   WinTitle : 対象Window (省略時:アクティブウィンドウ)
;   戻り値  1:ON 0:OFF
;-----------------------------------------------------------
{
    ifEqual WinTitle,,  SetEnv,WinTitle,A
    WinGet,hWnd,ID,%WinTitle%
    DefaultIMEWnd := DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hWnd, Uint)

    ;Message : WM_IME_CONTROL  wParam:IMC_GETOPENSTATUS
    DetectSave := A_DetectHiddenWindows
    DetectHiddenWindows,ON
    SendMessage 0x283, 0x005,0,,ahk_id %DefaultIMEWnd%
    DetectHiddenWindows,%DetectSave%
    Return ErrorLevel
}

IME_SET(setSts, WinTitle="")
;-----------------------------------------------------------
; IMEの状態をセット
;    対象： AHK v1.0.34以降
;   SetSts  : 1:ON 0:OFF
;   WinTitle: 対象Window (省略時:アクティブウィンドウ)
;   戻り値  1:ON 0:OFF
;-----------------------------------------------------------
{
    ifEqual WinTitle,,  SetEnv,WinTitle,A
    WinGet,hWnd,ID,%WinTitle%
    DefaultIMEWnd := DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hWnd, Uint)

    ;Message : WM_IME_CONTROL  wParam:IMC_SETOPENSTATUS
    DetectSave := A_DetectHiddenWindows
    DetectHiddenWindows,ON
    SendMessage 0x283, 0x006,setSts,,ahk_id %DefaultIMEWnd%
    DetectHiddenWindows,%DetectSave%
    Return ErrorLevel
}

;===========================================================================
; IME 入力モード 取得 / セット
;
;    0000xxxx    かな入力
;    0001xxxx    ローマ字入力
;    xxxx0xxx    半角
;    xxxx1xxx    全角
;    xxxxx000    英数
;    xxxxx001    ひらがな
;    xxxxx011    ｶﾅ/カナ
;
;     0 (0x00  0000 0000) かな    半英数
;     3 (0x03  0000 0011)         半ｶﾅ
;     8 (0x08  0000 1000)         全英数
;     9 (0x09  0000 1001)         ひらがな
;    11 (0x0B  0000 1011)         全カタカナ
;    16 (0x10  0001 0000) ローマ字半英数
;    19 (0x13  0001 0011)         半ｶﾅ
;    24 (0x18  0001 1000)         全英数
;    25 (0x19  0001 1001)         ひらがな
;    27 (0x1B  0001 1011)         全カタカナ

IME_GetConvMode(WinTitle="")
;-------------------------------------------------------
; IME 入力モード取得
;   in  WinTitle    (省略時アクティブウィンドウ)
;   戻り値:  入力モード
;--------------------------------------------------------
{
    ifEqual WinTitle,,  SetEnv,WinTitle,A
    WinGet,hWnd,ID,%WinTitle%
    DefaultIMEWnd := DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hWnd, Uint)

    ;Message : WM_IME_CONTROL  wParam:IMC_GETCONVERSIONMODE
    DetectSave := A_DetectHiddenWindows
    DetectHiddenWindows,ON
    SendMessage 0x283, 0x001,0,,ahk_id %DefaultIMEWnd%
    DetectHiddenWindows,%DetectSave%
    Return ErrorLevel
}

IME_SetConvMode(ConvMode,WinTitle="")
;-------------------------------------------------------
; IME 入力モードセット
;   in  ConvMode    入力モード
;       WinTitle    (省略時アクティブウィンドウ)
;--------------------------------------------------------
{
    ifEqual WinTitle,,  SetEnv,WinTitle,A
    WinGet,hWnd,ID,%WinTitle%
    DefaultIMEWnd := DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hWnd, Uint)

    ;Message : WM_IME_CONTROL  wParam:IMC_SETCONVERSIONMODE
    DetectSave := A_DetectHiddenWindows
    DetectHiddenWindows,ON
    SendMessage 0x283, 0x002,ConvMode,,ahk_id %DefaultIMEWnd%
    DetectHiddenWindows,%DetectSave%
    Return ErrorLevel
}

;===========================================================================
; IME 変換モード
;    0:無変換
;    1:人名/地名
;    8:一般
;   16:話し言葉優先

IME_GetSentenceMode(WinTitle="")
;-------------------------------------------------------
; IME 変換モード取得
;   in  WinTitle    (省略時アクティブウィンドウ)
;   戻り値:  0:無変換 1:人名/地名 8:一般 16:話し言葉優先
;--------------------------------------------------------
{
    ifEqual WinTitle,,  SetEnv,WinTitle,A
    WinGet,hWnd,ID,%WinTitle%
    DefaultIMEWnd := DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hWnd, Uint)

    ;Message : WM_IME_CONTROL  wParam:IMC_GETSENTENCEMODE
    DetectSave := A_DetectHiddenWindows
    DetectHiddenWindows,ON
    SendMessage 0x283, 0x003,0,,ahk_id %DefaultIMEWnd%
    DetectHiddenWindows,%DetectSave%
    Return ErrorLevel
}

IME_SetSentenceMode(SentenceMode,WinTitle="")
;-------------------------------------------------------
; IME 変換モードセット
;   in  SentenceMode 0:無変換 1:人名/地名 8:一般 16:話し言葉優先
;       WinTitle     (省略時アクティブウィンドウ)
;--------------------------------------------------------
{
    ifEqual WinTitle,,  SetEnv,WinTitle,A
    WinGet,hWnd,ID,%WinTitle%
    DefaultIMEWnd := DllCall("imm32\ImmGetDefaultIMEWnd", Uint,hWnd, Uint)

    ;Message : WM_IME_CONTROL  wParam:IMC_SETSENTENCEMODE
    DetectSave := A_DetectHiddenWindows
    DetectHiddenWindows,ON
    SendMessage 0x283, 0x004,SentenceMode,,ahk_id %DefaultIMEWnd%
    DetectHiddenWindows,%DetectSave%
    Return ErrorLevel
}

```

## まとめ

レジストリの変更、AutoHotKey、WinA1314等を使い、Apple Wiress Keyboard (英字配列) でWindowsでMac風のキーバインドで扱えるようにした。
多少面倒だけどMacとほぼ同じ操作感になったのでAutoHotKeyさまさまといったところ。