Windows7 Multitouch API (3)

こちらで触れたように Multitouch 周りは Windows7 ベータの時と仕様が若干
変わっています。なかなか試せず時間がたってしまいました。
ベータの WM_TOUCH

Multitouch API には 2系統あります。WM_TOUCH と WM_GESTURE です。
WM_TOUCH は複数の点の座標をそのまま送ってくるメッセージ、WM_GESTURE は
ある程度の動作を判断したあとに送られてきます。
両者は共存できないので、あらかじめどちらを使うか切り替えておくことになります。

ベータの時は WM_TOUCHDOWN, WM_TOUCHUP, WM_TOUCHMOVE と 3種類
メッセージがありました。RC 以降は WM_TOUCH 一つにまとめられています。
WM_TOUCH 系は複数のタッチ点の座標を一度に送信してくるため、それぞれ個別に
DOWN/UP する可能性があります。受け取った構造体の TOUCHINPUT には個別に
UP/DOWN/MOVE フラグが立っているので情報としては十分です。
複数の点をまとめて WM_TOUCHDOWN/TOUCHUP/TOUCHMOVE とひとくくりに
なっていたのは GESTURE のような操作を想定していたからかもしれません。

少々不思議なのは個別の UP/DOWN/MOVE は本当に区別できるのかということ。
座標はその瞬間サンプリングされたタッチ点なので厳密には個々のポイントを区別
することができず、連続性を持った値になるとは限りません。
例えば移動中のマルチタッチ点が増えたとして、どの点が新規にタッチされたものか
区別しなければならないということです。
サンプリングレートが十分速くて移動が限られている UI 操作ならそれほど問題
ないのかもしれません。
WM_TOUCH のイベントでは Windows 側で同一点の処理が行われており、
TOUCHINPUT の dwID に識別番号が入っています。
dwID が同じものを見ていくと DOWN ~ MOVE ~ UP の流れを見ることが
できるわけです。

lparam がハンドルなので、GetTouchInputInfo() で詳細を受け取ります。
これもベータ時の HANDLE から HTOUCHINPUT に変更されているようです。

void WM_Touch( UINT mes, WPARAM wparam, LPARAM lparam )
{
    int inputs= LOWORD( wparam );
    TOUCHINPUT  tbuf[ 32 ]; // inputs
    HTOUCHINPUT	hinput= reinterpret_cast( lparam );
    if( GetTouchInputInfo( hinput, inputs, tbuf, sizeof(TOUCHINPUT) ) ){
        TOUCHINPUT*  tp= tbuf;
        for( int i= 0 ; i< inputs && i < 32 ; i++, tp++ ){
            ~
	    tp->dwID // 識別
	    tp->x, tp->y // 座標
	    tp->dwFlags // UP/DOWN/MOVE
	}
    }
    CloseTouchInputHandle( hinput );
}

実際の 2点タッチだとこんな感じです。

0:(34054,41033) ID=3 flag=3a mask=4 ex=0 cx=4881 cy=5874 DOWN INRANGE PRIMARY NOCOALESCE 

0:(34054,41033) ID=3 flag=39 mask=4 ex=0 cx=4881 cy=5874 MVOE INRANGE PRIMARY NOCOALESCE 
1:(46230,31629) ID=4 flag=2a mask=4 ex=0 cx=5162 cy=5057 DOWN INRANGE NOCOALESCE 

0:(34007,40957) ID=3 flag=19 mask=4 ex=0 cx=5179 cy=5057 MVOE INRANGE PRIMARY 
1:(46224,31614) ID=4 flag=09 mask=4 ex=0 cx=4974 cy=5874 MVOE INRANGE 

0:(33966,40880) ID=3 flag=39 mask=4 ex=0 cx=5121 cy=5061 MVOE INRANGE PRIMARY NOCOALESCE 
1:(46212,31600) ID=4 flag=29 mask=4 ex=0 cx=4951 cy=5877 MVOE INRANGE NOCOALESCE 

0:(33796,40627) ID=3 flag=39 mask=4 ex=0 cx=5121 cy=5061 MVOE INRANGE PRIMARY NOCOALESCE 
1:(46330,31582) ID=4 flag=29 mask=4 ex=0 cx=4951 cy=5877 MVOE INRANGE NOCOALESCE 

0:(33632,40378) ID=3 flag=39 mask=4 ex=0 cx=4916 cy=5068 MVOE INRANGE PRIMARY NOCOALESCE 
1:(46447,31563) ID=4 flag=29 mask=4 ex=0 cx=4904 cy=5870 MVOE INRANGE NOCOALESCE 

0:(33082,39298) ID=3 flag=39 mask=4 ex=0 cx=4916 cy=5068 MVOE INRANGE PRIMARY NOCOALESCE 
1:(46757,31680) ID=4 flag=29 mask=4 ex=0 cx=4904 cy=5870 MVOE INRANGE NOCOALESCE 

0:(32531,38217) ID=3 flag=19 mask=4 ex=0 cx=3779 cy=5108 MVOE INRANGE PRIMARY 
1:(47074,31801) ID=4 flag=09 mask=4 ex=0 cx=4464 cy=5870 MVOE INRANGE 

0:(32531,38217) ID=3 flag=34 mask=4 ex=0 cx=3779 cy=5108 UP PRIMARY NOCOALESCE 
1:(47074,31801) ID=4 flag=29 mask=4 ex=0 cx=4464 cy=5870 MVOE INRANGE NOCOALESCE 

0:(47074,31801) ID=4 flag=24 mask=4 ex=0 cx=4464 cy=5870 UP NOCOALESCE 

座標値をピクセルに変換するには TOUCH_COORD_TO_PIXEL()。

HP TouchSmart IQ800 を使っていますが、たまに multi touch が無効になっている
ことがあります。何らかの更新のタイミングで、別のドライバに上書きされて
しまっているようです。ドライバを入れ直すと再び使えるようになります。

nextwindow Windows 7 Touch Screen Driver

関連エントリ
Windows SDK for Windows7 RC と Multitouch / Direct3D 11
Windows7 Multitouch API その(2) WM_GESTURE 系
Windows7 Multitouch API