Windows7 Multitouch API その(2) WM_GESTURE 系

Windows7 のマルチタッチ系イベントには二通りあることを前回説明しました。
高度な方、WM_GESTURE 系についてもう少し詳しくさわってみます。

メッセージは WM_MOUSEMOVE のように座標の更新毎に多数送られてきます。
このとき一つの操作の組が GID_BEGIN と GID_END で囲まれます。
例えば PAN 操作の場合

GID_BEGIN
GID_PAN
GID_PAN
GID_PAN
GID_PAN
...
GID_END

といった感じに。
また別の操作が認識されれば、それらが GID_BEGIN~GID_END で囲まれます。
マウスでいえば LBUTTONDOWN / LBUTTONUP のようなもの。
タッチだと WM_TOUCHDOWN / WM_TOUCHUP でしょう。
開始と終了が明確にわかるようになっています。

ただ上の例だと最初と最後の GID_PAN 自身にも GF_BEGIN, GF_END フラグが
追加されているので、実は GID_BEGIN/GID_END を無視しても何も困りません。
フラグ値を追加して書き直してみます。

GID_BEGIN
GID_PAN  GF_BEGIN
GID_PAN
GID_PAN
...
GID_PAN
GID_PAN  GF_INERTIA
...
GID_PAN  GF_INERTIA
GID_PAN  GF_INERTIA|GF_END
GID_END

GF_INERTIA は PAN 操作のみ追加される慣性で、操作後もしばらくメッセージが
送られてきます。

前回も書きましたがマニュアルにはまだ間違いが含まれているので、仕様が確定
するまではヘッダファイルを見た方が確実です。ヘッダは WinUser.h です。

WM_GESTURE が送ってくる座標値はスクリーン座標です。
GESTUREINFO 構造体には対象となるウィンドウのハンドルが含まれていますが、
ウィンドウ内の座標系に変換する場合は自分で行う必要があります。

一本指のシングルタッチなどはマウスと同じ扱いなので、マウス系のメッセージを
処理する必要があります。よってフリック操作はマウス扱いです。

パンや回転、ズーム(2点間の距離)などの操作は結構誤動作というかノイズが入るようです。
極端に異なる値が来たときは無視するような処理が必要になるかもしれません。
また GID_ROTATE の最初のメッセージには回転値として不正な値が入っているようです。
GID_ROTATE かつ GF_BEGIN が立っている場合、ullArguments の下位 16bit を 0 と
見なした方がよいです。
回転しようとすると必ず反転してしまうおかしな症状に最初悩みました。

用途によるとは思いますが、やはり凝ったことを行いたい場合は WM_GESTURE ではなく
WM_TOUCH 系 (WM_TOUCHUP/WM_TOUCHDOWN/WM_TOUCHMOVE) を
使った方が良さそうです。
WM_GESTURE の場合操作判定が先に行われてしまうので、操作の位置を制限することが
難しくなります。
例えば特定のオブジェクトの上だけで回転やズームを行い、それ以外の座標では
常にパン操作と判定したい場合などあまりきれいに操作を区別することができません。

最初は簡単に見えたものの、実際にやってみるとまだまだ。
プログラムの方もいろいろと工夫が必要になりそうです。

関連エントリ
Windows7 Multitouch API