タッチ関連の API は 2種類あります。
WM_TOUCH 系と WM_GESTURE 系
WM_TOUCH 系の方が低レベルで、直接複数のタッチ座標を取り出すことが出来ます。
WM_GESTURE の方はいくつかの決まった操作を容易に受け取ることができます。
WM_TOUCH 系のメッセージを有効にするには RegisterTouchWindow() を呼び出します。
これを実行しておかないと WM_TOUCH~ が送られて来ません。
データを受け取るのは簡単です。
WM_TOUCHDOWN
WM_TOUCHUP
WM_TOUCHMOVE
などマウスとよく似ているメッセージが来るので、さらに
GetTouchInputInfo() を使って詳細な情報を読み取ります。
起動時の判定
// ハードがマルチタッチをサポートしているかどうか int value= ~GetSystemMetrics( SM_DIGITIZER ); if( !(value & 0xc0) ){ RegisterTouchWindow( hwnd, 0 ); }
メッセージ
case WM_TOUCHDOWN: case WM_TOUCHUP: case WM_TOUCHMOVE: WM_Touch( mes, wparam, lparam ); return FALSE;
読み出しの例
void WM_Touch( UINT mes, WPARAM wparam, LPARAM lparam ) { int inputs= LOWORD( wparam ); TOUCHINPUT tbuf[TOUCHMAX]; HANDLE hinput= reinterpret_cast( lparam ); if( GetTouchInputInfo( hinput, inputs, tbuf, sizeof(TOUCHINPUT) ) ){ TOUCHINPUT* tp= tbuf; for( int i= 0 ; i< inputs ; i++, tp++ ){ ... } } CloseTouchInputHandle( hinput ); }
座標値そのままなので、これを元にズームや回転などの操作を検出するには
さらに一手間いります。
WM_GESTURE 系はそのあたりを簡単にしてくれます。
下記の操作が定義されています。
GID_ZOOM
GID_PAN
GID_ROTATE
GID_TWOFINGERTAP
GID_ROLLOVER
これらのメッセージは RegisterTouchWindow() を実行すると来なくなるので
WM_GESTURE 系を使う場合は RegisterTouchWindow() を実行してはいけません。
WM_GESTURE が送られてきたらさらに追加情報を受け取ります。
case WM_GESTURE: WM_Gesture( mes, wparam, lparam ); return FALSE;
void WM_Gesture( UINT mes, WPARAM wparam, LPARAM lparam ) { GESTUREINFO ginfo; memset( &ginfo, 0, sizeof(GESTUREINFO) ); ginfo.cbSize= sizeof(GESTUREINFO); HGESTUREINFO hgesture= reinterpret_cast( lparam ); if( GetGestureInfo( hgesture, &ginfo ) ){ ... } CloseGestureInfoHandle( hgesture ); }
WM_GESTURE 系の仕様は若干変更があったようで、資料によっては記載内容が
異なっていることがあります。例えば今でも
このページにある dwCommand は存在しておらず GESTUREINFO 構造体の
dwID のことだと思われます。
同じように dwArgument も 64bit の ullArguments に変更されているようです。
・dwCommand → GESTUREINFO dwID
・dwArgument → GESTUREINFO ullArguments
・lParam → GESTUREINFO ptsLocation
その他いくつか気が付いた点。
初期状態では GID_ROTATE などのメッセージが来ませんでした。
SetGestureConfig() を使って送って欲しいメッセージの登録が出来るようです。
const int ConfigCount= 5; GESTURECONFIG config[ConfigCount]; memset( config, 0, sizeof(GESTURECONFIG) * ConfigCount ); config[0].dwID= GID_ZOOM; config[0].dwWant= GC_ZOOM; config[1].dwID= GID_PAN; config[1].dwWant= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY |GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY |GC_PAN_WITH_GUTTER |GC_PAN_WITH_INERTIA; config[2].dwID= GID_ROTATE; config[2].dwWant= GC_ROTATE; config[3].dwID= GID_TWOFINGERTAP; config[3].dwWant= GC_TWOFINGERTAP; config[4].dwID= GID_ROLLOVER; config[4].dwWant= GC_ROLLOVER; SetGestureConfig( hwnd, 0, 5, config, sizeof(GESTURECONFIG) );
これで全部のメッセージとオプションが有効になるはずです。
座標は ptsLocation に、追加パラメータは ullArguments に入ります。
GID_PAN + GF_INERTIA フラグが ON の場合は、ullArguments の上位 32bit に
慣性のパラメータが格納されているようです。
GID_INERTIA というのは存在していません。
なお、これらの動作を確認するには
・Windows7 Beta
・Windows SDK for Windows 7 BETA
・MultiTouch 対応 PC
が必要です。Vista では起動時に DLL の互換性が無くエラーになります。
HP の TouchSmart PC IQ800 を使いました。
Windows7 SDK の設定には少々注意が必要です。
新しい DirectX SDK もリリースされているので、DirectX SDK March 2009 を
併用する場合は特に。基本的にあとからリリースされた方を上にします。
・DirectX SDK March 2009
・Windows SDK for Windows 7 BETA
・VisualStudio 2008
VisualStudio の Tools → Options → Projects and Solutions → VC++ DIrectories の設定
Include files $(DXSDK_DIR)include $(WindowsSdkDir)\include $(VCInstallDir)include ~ Library files (x64) $(DXSDK_DIR)lib\x64 $(WindowsSdkDir)lib\x64 $(VCInstallDir)lib\amd64 ~ Library files (x86) $(DXSDK_DIR)lib\x86 $(WindowsSdkDir)lib $(VCInstallDir)lib ~
またあらかじめスタートメニュー Microsoft Windows SDK v7.0 から
Windows SDK Configuration Tool を起動して v7.0 を選択しておきます。
関連エントリ
・DirectX SDK March 2009
・Windows7 とマルチタッチ / HP TouchSmart PC IQ800
・Direct2D と Direct3D10.1 の下位互換