W-ZERO3シリーズのキーボードとキーコード

gKanaInputのキー割り当てを考えるにあたってキーボードとキーコードを少し調べたんですが、折角なんでまとめてみようかなと。今回もホーミンさんのvkeycheckerを使っています。
※9/18追記:WS007SHの[Fn]+[K]と[Fn]+[L]についての情報を追加
キーの押し離しはDOWN/UPまたはD/Uで表記します。基本的にWS011SHのキーコンビネーションで話を進めますが、WS007SH以前の機種とは互換があるので、存在しない部分を除けばそのまま使用可能です。また、本来は英数キーにキーコードの別名は無いのですが、コードを直接書いても判りにくいので、仮にVK_A〜VK_Z、VK_0〜VK_9の別名を割り当てました。
それでは、まずは[Shift]/[Ctrl]キーの短押しから。デスクトップPCとの最大の違いがこの短押しで、短押しした後の1回のキー操作だけ、そのキーを押しながらとして扱われるわけですが、キーコード的にはDOWNなら入力したキーの前に、UPなら後に[Shift]/[Ctrl]キーのDOWN/UPコードがくっつけられて送られます。例えば、[Shift]キー短押しの後に[A]キーを押すとこんな感じです。

D VK_SHIFT
U VK_SHIFT
D VK_SHIFT
D VK_A
U VK_A
U VK_SHIFT

上2行が[Shift]キー短押し、下4行が[Shift]キー短押し効果付きの[A]キーということで、まあ、見た目通りのコードが送られているわけですが、ここで落とし穴が1つ。キーコードが「くっつけられて送られる」と書きましたが、まさに言葉どおり「くっついて」いて、間に割り込むことができません。
例えば上記の例で、キーフックを掛けて、3行目のVK_SHIFTのDOWNが渡ってきた時点で[B]キーDOWN/UPのコードを送って割り込ませたとすると、並び順が期待したとおりになりません。実際にはこんな感じになります。

D VK_SHIFT
U VK_SHIFT
D VK_SHIFT ←で処理したのに
D VK_A     ←ではなく
D VK_B     ←に入ってしまう
U VK_B
U VK_A
U VK_SHIFT

普段使う分には気にする必要は無いのですが、キーフックでキーコードの置き換えをしようとすると問題になります。gKanaInput/gBraceBracketでは、[Shift]のコードは後に続くコードとセットで処理することで回避していますが、かなり面倒くさいです。
[Fn]キーの短押しの場合は、キーフックルーチンに渡ってきた時点ですでにコードが変わっているので特例処理は必要ありませんが、内部的には同様に処理されているようです。
ちなみに、短押しの効果は[Fn]/[Shift]/[Ctrl]自身にも効くので、例えば[Shift]キーを2回押すとキーコードはこんな感じで送られます。結構間抜けです。

D VK_SHIFT
U VK_SHIFT
D VK_SHIFT
D VK_SHIFT
U VK_SHIFT
U VK_SHIFT

このような組み合わせの場合キーコードは送られますが、その後の短押しの効果は消滅しますので、間違ってこれらのキーを短押ししてしまった場合の短押し効果のキャンセルに使えるんではないかと。また、このせいで短押し+短押しは機能しません。
続いては、[Fn]/[Shift]/[Ctrl]キーの短押しの後、[Fn]/[Shift]/[Ctrl]を押しながらキー入力した場合。組み合わせとしては以下があるわけですが、全部が全部使えるわけではありません。「○」はキーコードが全て([Fn]を除いて)きちんと送られるもの、「×」は送られないものです。

コード キーコンビネーション 備考
× [Fn]短押し+[Shift] [CapsLock]
× [Fn]短押し+[Ctrl]+キー [Ctrl]キーコード消滅
[Shift]短押し+[Fn]+キー -
[Shift]短押し+[Ctrl]+キー 動作は[Ctrl]優先
[Ctrl]短押し+[Fn]+キー -
[Ctrl]短押し+[Shift]+キー 動作は[Ctrl]優先

このうち、[Shift]短押し+[Fn]+キーの組み合わせでは、色々な代替入力を使うことが出来ます。それを一覧にしたのが以下の表です。

代替入力 文字 本来の入力 備考
[Shift]短押し+[Fn]+[Y] [Fn]+[半角/全角] -
[Shift]短押し+[Fn]+[U] [Fn]+[Q] -
[Shift]短押し+[Fn]+[I] [Fn]+[W] -
[Shift]短押し+[Fn]+[H] [Fn]+[E] -
[Shift]短押し+[Fn]+[J] [Fn]+[R] -
[Shift]短押し+[Fn]+[K] [Fn]+[T] -
[Shift]短押し+[Fn]+[B] [Fn]+[S] -
[Shift]短押し+[Fn]+[N] [Fn]+[D] -
[Shift]短押し+[Fn]+[M] [Fn]+[F] -
[Shift]短押し+[Fn]+[.] [Fn]+[G] 代替入力と本来の入力でコードが違う
[Shift]短押し+[Fn]+[,] [Fn]+[L] 代替入力と本来の入力でコードが違う
- [Fn]+[K] WS007SH以前・WS011SHとはコードが違う
- [Fn]+[L] WS007SH以前・WS011SHとはコードが違う
[Shift]短押し+[Fn]+[X] [Fn]+[C] -
[Shift]短押し+[Fn]+[W] [Fn]+[E] WS007SH以前
[Shift]短押し+[Fn]+[-] [Fn]+[V] -
[Shift]短押し+[Fn]+[-] [Fn]+[R] WS007SH以前
[Shift]短押し+[Fn]+[/] [Fn]+[C] -
[Shift]短押し+[0] [Fn]+[E] WS007SH以前
[Shift]短押し+[Fn]+[P] - 全機種

コードが違うと書かれている4つは、入力される文字が同じだけで、実際には同じキーコードにはなっていません(厳密に言えばその他のキーも同じではないのですがそれはこの後で)。どうなっているかといえば、こうなっていたりします。

[Shift]短押し+[Fn]+[.]
D VK_SHIFT
U VK_SHIFT
D VK_SHIFT
D VK_APOSTROPHE
U VK_APOSTROPHE
U VK_SHIFT
[Fn]+[G]
D VK_MULTIPLY
U VK_MULTIPLY
WS007SH・[Fn]+[K]
D VK_SHIFT
D VK_APOSTROPHE
U VK_SHIFT
D VK_SHIFT
U VK_APOSTROPHE
U VK_SHIFT
[Shift]短押し+[Fn]+[,]
D VK_SHIFT
U VK_SHIFT
D VK_SHIFT
D VK_SEMICOLON
U VK_SEMICOLON
U VK_SHIFT
[Fn]+[L]
D VK_ADD
U VK_ADD
WS007SH・[Fn]+[L]
D VK_SHIFT
D VK_SEMICOLON
U VK_SHIFT
D VK_SHIFT
U VK_SEMICOLON
U VK_SHIFT

WS011SHの[Fn]+[G]と[Fn]+[L]はテンキー側のキーのコードで、WS007SHの[Fn]+[K]と[Fn]+[L]はフルキー側のキーコードを[Shift]キーでサンドイッチし、代替キーはフルキー側のキーのコードに[Shift]短押し効果を組み合わせて、それぞれ送られています。このように処理されているので、WS011SHの[Fn]+[G]と[Fn]+[L]の2つのキーコンビネーションは、キーマクロ系のソフトで別のキーに置き換えが可能なんじゃないかと思います。
それじゃあ他のキーはどうなのか? ということで"#"のコードを例として挙げますが、こんな感じになっています。

[Shift]短押し+[Fn]+[I]
D VK_SHIFT
U VK_SHIFT
D VK_SHIFT
D VK_3
U VK_3
U VK_SHIFT
[Fn]+[W]
D VK_SHIFT
D VK_3
U VK_SHIFT
D VK_SHIFT
U VK_3
U VK_SHIFT

うーん、WS007SHの[Fn]+[K]/[Fn]+[L]といいこれといい、どこかで見たようなサンドイッチなキーコードです(苦笑)。さらに厄介なことに、サンドイッチ1つごとに「くっついて」います。この場合は上3行と下3行で2つのブロックに分かれている感じです。gKanaInput/gBraceBracketではそれを逆手に取って、代替入力と[Fn]+キー直接入力の区別をつけていたりするのですが、単純な判定だと、この2つの区別は付けられないんじゃないかと思います。どちらも[Shift]キーが押されていることには変わりがないわけですからね。
ここで、代替入力で[Shift]短押し+[Fn]+キーのキーコンビネーションを使えてるなら、[Fn]+[W]なんかに対しても使えるんじゃないか? と思った貴方は鋭い。一応、こんな感じでキーコードが送られてきます。

[Shift]短押し+[Fn]+[W]
D VK_SHIFT
D VK_SHIFT
D VK_3
U VK_SHIFT
D VK_SHIFT
U VK_3
U VK_SHIFT
U VK_SHIFT

なお、このキーコンビネーションには少々癖があって、最初のVK_SHIFTのDOWNは[Fn]キーのDOWNと同時に、最後のVK_SHIFTのUPは[Fn]キーのUPと同時に送られてきますので、要するに[Fn]キーを離さない限り[Shift]も押されっぱなしになり、ちょっとおかしな挙動を示します。
ちなみに、gKanaInput/gBraceBracketでは[Shift]キーをネストする処理を加えてあるので、これもきちんと検出することができます(でないと[Shift]短押し+[Fn]+[C]で"{"は入力できません)。

そんなわけで、長々と書いてきましたが、今回の解析で解った情報はここまでです。WindowsMobileは専門外なんで「そんなの常識だ」と言われてしまう情報も含まれているかもしれませんが、そこはそれ、ご容赦いただければと。
ではでは。