Xcrawlの上手い使い方?

XcrawlはAdvanced/W-ZERO3[es]での新要素なわけですが、キーコードの入り方が特殊なため、扱いに困っている人が多いみたいですね。GSFinderをXcrawl対応にすべく調べてみたので、その調査結果なんかを書いてみようかと。
ちなみにXcrawlのキーコードはこんな感じで入ってきます。今回はスキャンコードが表示されないvkeycheckerでは調べられないネタなので*1、gBraceBracketにデバッグ用コードを埋め込んでコードを調べています。

Xcrawl上
D VK_UP
D VK_F20
U VK_UP
U VK_F20
Xcrawl下
D VK_DOWN
D VK_F20
U VK_DOWN
U VK_F20

KEYDOWN時のVK_F20が先に出ていれば、VK_F20でフラグを立て下ろししてVK_UP/VK_DOWNを処理し分けることが簡単にできるんでしょうが、何故か押下時もVK_UP/VK_DOWNが先という妙な並び。ちょっとググってみたら「VK_F20でフラグを立ててKEYUPで処理を行えば……」みたいな方法が書かれていたりして、苦労の跡が偲ばれます。
ところがこれ、ちょっと工夫すると、条件判断を1〜2個追加するだけで判定できてしまったりするんです。その仕掛けは「スキャンコード」。WM_KEYDOWN/WM_KEYUPメッセージが送られてくると、メッセージのパラメータ(lParam)にこのスキャンコードが入ってくるのですが、キーコード的に同じキーでも、物理的に違うキーであれば違うスキャンコードが入ります。
今回の場合、VK_UP/VK_DOWNが通常のカーソルキーとXcrawlで重複するので、これが判定できればいいわけです。じゃあ、カーソルキーのスキャンコードはどうなってるのか、というと……。

テンキー(Xcrawl)側カーソルキー
VK_UP:0xC3(フルキー閉)/0xC0(フルキー開)
VK_DOWN:0xC2(フルキー閉)/0xC1(フルキー開)
フルキー側カーソルキー
VK_UP:0x3B
VK_DOWN:0x3C
Xcrawlの内部コードでのカーソルキー
VK_UP:0x00(フルキー状態に関わらず)
VK_DOWN:0x00(フルキー状態に関わらず)

ご覧の通り、見事に数値が違います。ちなみにWindows APIの解説などの「スキャンコード」の項目には「この値はOEM依存です」などと書かれていて、いかにも触るなと言いたげですが、逆にいえば特定の機種だけに対応させるのであれば、使ってしまっても問題は無いのです。ファームウェアのバージョンによってスキャンコードが変わる可能性も無い訳ではありませんが、今のところW-ZERO3シリーズを通して見ても、2キー(WS007SHWS011SHにおける[,][.]キー)を除いて変更されていません*2
Xcrawlの発生させるVK_UP/VK_DOWNはスキャンコードが0x00なので、これで判定することができます。判定することさえできれば、あとは普通にWM_KEYUP/WM_KEYDOWNの処理を書くだけです。実装としては、

  • XcrawlのVK_UP/VK_DOWNと通常のVK_UP/VK_DOWNで処理を分ける
  • XcrawlのVK_UP/VK_DOWNを無視するようにしてVK_F20だけで処理する*3

あたりが適当なんではないかと思いますが、どうでしょうか。なお、GSFinderは他の機種でも使われるものなので、簡単にW-ZERO3であるかどうかを判定したうえで、W-ZERO3である場合にのみ前者のパターンでXcrawlを処理するようにしてみました。
ちなみに、ほとんどのキーフック系アプリではスキャンコードの処理がおざなりなので、キーフックアプリ側でVK_UP/VK_DOWNを生成させるとXcrawlの内部コードとの判別ができない可能性が高いです。これについては各キーフックアプリの作者による対応に期待することにします。ヒントはkeybd_eventということで。

*1:ホーミンさん、スキャンコードの表示機能付けてくださいよー(^^;)

*2:蛇足ながらEM・ONEでも同じスキャンコードだそうです

*3:UPとDOWNが判別できないので使えないですね(汗)