↓実際に開発に使用している、または所有しており自分で触ってみたもの。
PC | 同時認識 | sensor | touch補足 | 対応 API | display | CPU | GPU |
---|---|---|---|---|---|---|---|
HP TouchSmart IQ821jp | 2 点 | optical | NextWindow | Win7 Touch API | 25.5inch 1920×1200 | Core2 Duo P8600 2.4GHz | GeForce 9600M GS |
SHARP Meibus PC-NJ70A | ∞? | optical LCD | 開発× | SHARP 独自のみ | 4.0inch 854×480 (sub display) | Atom N270 | GMA950 |
iPhone 2G/3G/iPod touch | 5 点 | capacitive | iOS (iPhoneOS) | 3.5inch 480×320 | ARM11 412/533MHz | PowerVR MBX | |
iPhone 3GS/iPod touch | 5 点 | capacitive | iOS (iPhoneOS) | 3.5inch 480×320 | Cortex-A8 600MHz | PowerVR SGX 535 | |
iPad 3G/Wi-Fi | 11 点 | capacitive | iOS (iPhoneOS) | 9.7inch 1024×768 | Cortex-A8 1GHz | PowerVR SGX 535 | |
iPad2 3G/Wi-Fi | 11 点 | capacitive | iOS (iPhoneOS) | 9.7inch 1024×768 | Cortex-A9 1GHz x2 | PowerVR SGX 543MP | |
HTC Desire (X06HT) | 2 点 | capacitive | Android 2.x | 3.7inch 800×480 | Scorpion 1GHz | Adreno 200 (AMD Z430?) | |
iiyama ProLite T2250MTS | 2 点 | optical | Win7 Touch API | 21.5inch 1920×1080 | モニタのみ | ||
MouseComputer LuvPad AD100 | 2 点 | capacitive | Android 2.2 | 10.1inch 1024×600 | Cortex-A9 1GHz x2 | Tegra 250 | |
LG Optimus Pad L-06C | 10 点 | capacitive | Android 3.0 | 8.9inch 1280×768 | Cortex-A9 1GHz x2 | Tegra 250 |
↓店頭で実際に触って確認したもの。ペイントがわかりやすい。
PC | 同時認識 | sensor | touch補足 | 対応 API | display | CPU | GPU |
---|---|---|---|---|---|---|---|
Fujitsu LOOX U G90 | 5 点 | resistive | Win7 Touch API | 5.6inch 1280×800 | Atom Z520 1.33GHz | GMA500 (PowerVR SGX 535) | |
ASUS EeePC T91MT | 2 点 | resistive | Win7 Touch API | 8.9inch 1024×600 | Atom Z520 1.33GHz | GMA500 (PowerVR SGX 535) | |
ASUS EeePC T101MT | 2 点 | resistive | Win7 Touch API | 10.1inch 1024×600 | Atom N450 1.66GHz | GMA3150 | |
Lenovo IdeaPad S10-3t | 2 点 | capacitive | Win7 Touch API | 10.1inch 1024×600 | Atom N450 1.66GHz | GMA3150 | |
ASUS EeeTop ET2010AGT | 2 点 | optical | Win7 Touch API | 20.0inch 1600×900 | AthronII X2 250u 1.6GHz | ATI Mobility Radeon HD 5470 | |
Gateway ZX6800-43 | 2 点 | optical | Win7 Touch API | 23.0inch 1920×1080 | Core2 Duo E7500 2.93GHz | GMA X4500HD | |
Fujitsu FMV F/G60 | 2 点 | optical | Win7 Touch API | 20.0inch 1600×900 | Core i3-330M 2.13GHz | GMA HD | |
HP TouchSmart PC600 1190jp | 2 点 | optical | Win7 Touch API | 23.0inch 1920×1080 | Core i7-720QM 1.6GHz | GeForce GT230 | |
SONY VAIO L VPCL139FJ/T | 2 点 | optical | NextWindow | Win7 Touch API | 24.0inch 1920×1080 | Core2 Duo E7600 3.06GHz | GeForce 310M |
IODATA LCD-AD221FB-T | 2 点 | optical | Win7 Touch API | 21.5inch 1920×1080 | モニタのみ | ||
Let's note C1 | 2 点 | electromagnetic digitizer + capacitive | 複合 Wacom | Win7 Touch API | 12.1inch 1280×800 | Core i5-502M 2.4GHz | GMA HD |
SHARP IS01/SH-10B/JN-DK01 | 2 点? | capacitive | 開発× | Android 1.6で独自 | 5.0inch 960×480 | Scorpion 1GHz | Adreno 200 (AMD Z430?) |
Toshiba Libretto W100 | 2点 x 2面 | capacitive | 2面とも | Win7 Touch API | 7.0inch 1024×600 x2 | Pentium U5400 1.2GHz | GMA HD |
↓情報提供していただいた物。
PC | 同時認識 | sensor | touch補足 | 対応 API | display | CPU | GPU |
---|---|---|---|---|---|---|---|
ONKYO TW317A5 | 2点 | capacitive | Win7 Touch API | 11.6inch 1366×768 | Aton N450 1.66GHz | GMA3150 | |
GREEN HOUSE GH-JTJ223GSHB | 2点 | optical | Win7 Touch API | 21.5inch 1920×1080 | モニタのみ |
↓その他マルチタッチ可能と判明しているものや発売予定のものなど。
PC | 同時認識数 | sensor | touch補足 | 対応 API | display | CPU | GPU |
---|---|---|---|---|---|---|---|
Lenovo ThinkPad X201 Tablet | ? | electromagnetic digitizer + capacitive? | 複合 Wacom | Win7 Touch API | 12.1inch 1280×800 | Core i7-640LM | GMA HD |
Viliv S10 | 3 点 | resistive | Win7 Touch API | 10.1inch 1366×768 | Atom Z550 2.0GHz | GMA500 (PowerVR SGX 535) | |
iPhone 4 / iPod touch 4G | 5? | capacitive | iOS | 3.5inch 960×640 | Cortex-A8 | PowerVR SGX 535 | |
Samsung Galaxy S GT-I9000 | ∞? | capacitive | Android 2.x | 4.0inch 800×480 | Cortex-A8 1GHz | PowerVR SGX 540 | |
Dell SX2210T | 2 点 | optical | NextWindow | Win7 Touch API | 21.5inch 1920×1080 | モニタのみ | |
HP 2310t | 2 点 | optical | Win7 Touch API | 23.0inch 1920×1080 | モニタのみ | ||
HP 2209t | 2 点 | optical | Win7 Touch API | 21.5inch 1920×1080 | モニタのみ | ||
HP mini 5102 10H/160/Pro | Win7 Touch API | 10.1inch 1366×768 | Atom N450 1.66GHz | GMA3150 | |||
MSI E22T31-ITWH | 2 点 | optical | Win7 Touch API | 21.tinch 1920×1080 | Celeron T3100 1.9GHz | NVIDIA ION | |
MSI Wind Top AE2420 3D | touch+3D | Win7 Touch API |
複数のセンサーからの入力を受け取れる。
WM_TOUCH と WM_GESTURE の 2種類あり
WM_GESTURE の方が一見簡単に使えそうですが、判定はモーション完了後に行われるためワンテンポ遅れてあまり直感的ではありません。 最初にタッチしたオブジェクトで判定を切り替えたい場合も多く、意外にできないことも多くあります。 タッチを使った直接操作というより、ジェスチャーを使ったショートカットに近い。 実際に使うなら WM_TOUCH の方が良いと思います。
WM_TOUCH は WM_GESTURE より低レベルとはいえ、タッチ点がシステムで分離されているので扱いは容易です。 ID 分けされた各タッチ点毎に TOUCHEVENTF_MOVE/DOWN/UP で区別可能です。 識別 ID TOUCHINPUT::dwID は必ずしも 0 から始まるわけではないので要注意。
座標は整数値ですがサブピクセル情報を含んでおり TOUCH_COORD_TO_PIXEL() マクロで変換します。( 1/100 倍)
最初のタッチ点は特別に TOUCHEVENTF_PRIMARY としてマークされています。Primary はマウス扱いになります。 Primary 点を離した後は、いったんすべての接地点が無くなるまで Primary 扱いにはなりません。 例えば下記の 4 は Primary にならないので、他の点をタッチしたまま Primary だけダブルタップする場合注意が必要です。 このフラグはあてにしない方が良いかもしれません。
連続する MOVE message は多くの TOUCHEVENTF_NOCOALESCE で送られてきますが、このフラグが無いメッセージのみサンプルすることで、 ある程度取りまとめて判定することが可能です。 RegisterTouchWindow() 時に TWF_FINETOUCH を指定するとすべて NOCOALESCE になります。
cxContact/cyContact は設置面積 (pixel 数) を表します。dwMask に TOUCHINPUTMASKF_CONTACTAREA がある場合のみ有効です。 光学式でも値が取れることを確認。
デフォルトは WM_GESTURE なので、あらかじめ RegisterTouchWindow( hWnd, 0 ) を実行しておく必要があります。
TOUCHEVENTF_PRIMARY のタッチは WM_LBUTTONDOWN/WM_LBUTTONUP/WM_MOUSEMOVE 等のマウスイベントも発生させます。 アプリケーションをマウスとマルチタッチの両操作対応にすると、マルチタッチ中なのに同時にマウス側の処理も多重に行われる可能性があります。 MSDN Troubleshooting Applications によると下記の方法で判別できるそうです。
#define MOUSEEVENTF_FROMTOUCH 0xFF515700 if( (GetMessageExtraInfo() & MOUSEEVENTF_FROMTOUCH) == MOUSEEVENTF_FROMTOUCH ){ // Click was generated by wisptis / Windows Touch }else{ // Click was generated by the mouse. }
Windows 7 のデフォルト設定では、最初のタッチ時に即座に TOUCHEVENTF_DOWN が発生しません。 下記の何らかの動作を行って初めて DOWN と UP (または MOVE) が同時に発生します。
Windows 7 で プレス アンド ホールド (長押し) 操作が有効になっていることが原因です。 タッチしたタイミングが分からずディレイが発生するのでゲームなどに向きません。 下記の設定で直るようです。
これで最初のタッチですぐに TOUCHEVENTF_DOWN が発生するようになります。 ただし通常のウィンドウ操作でも長押し(プレス アンド ホールド)で右ボタンメニューが出なくなるので注が必要です。
Android OS 2.0 (API Level 5) で導入されています。
タッチ点の ID 分離をシステムが行ってくれるため扱いは容易です。 ただし pointer Index 値は 0 からの連番となり絶対 ID ではないので要注意。 2 点タッチ中に Primary が ACTION_UP すると Secondary が index 0 に繰り上げられます。
index の代わりに固有 ID (pointerId) を使った識別ができます。この場合 index と違い繰上問題が起こりません。詳細は後述。
タッチ操作の精度を上げるには大量のサンプリング点が必要ですが、 イベントの発生頻度を抑える工夫が行われているようです。 Windows7 でいえばおそらく TOUCHEVENTF_NOCOALESCE がついていない (COALESCE された) メッセージに相当し、その間のポイントは History として参照できます。
ACTION_DOWN, ACTION_UP でも同時にタッチされている点がすべて報告されるので、実際に変化のあったタッチ点を得るには下記の演算で求まる index 値が必要です。
(event.getAction() & event.ACTION_POINTER_ID_MASK) >> event.ACTION_POINTER_ID_SHIFT
API Level 8 (Android OS 2.2 Froyo) からは上の計算の代わりに event.getActionIndex() が使えるようになります。
座標値は Windows7 と違い浮動小数 float が用いられています。
マルチタッチ時に、タッチされている点への情報アクセスに使う index。0 ~ event.getPointerCount()-1。 event.getPointerCount() は同時にタッチされている点の数。
なお ACTION_UP 時は UP された座標の通知のために 2点送られて来るが、厳密にはこのタイミングでは触っているのは 1点になっている。
History Table の index 番号。 0 ~ event.getHistorySize()-1 。 ACTION_MOVE 時に軌跡を補間する。 マルチタッチの場合は、各点毎に HistorySize 分の値が入っている。
ACTION_MOVE 以外では使わない。このとき event.getHistorySize() は常に 0 となる。
タッチ点を識別する固有 ID 値。 pointerIndex と違って繰上が行われず、固有値として用いることができる。 pointerIndex と相互変換して使う。
pointerIndex → pointerId 変換 | pointerId= event.getPointerId( pointerIndex ) |
pointerId → pointerIndex 変換 | pointerIndex= event.findPointerIndex( pointerId ) |
HTC Desire のパネルは 10msec サンプリング。 およそ 100Hz。 Move Event は約 30msec 毎に取りまとめられている。 移動値が少ないと頻度が下がるので、時間ではなく移動量かもしれません。
タッチポイント分、複数の UITouch がそのまま通知されます。 マルチタッチ時の通知は変化があったポイント座標のみで必要最小限です。 Android のように同時にタッチされている点が全部通知されることがありません。
個々のタッチ点の固有の追跡は行われていないようで、タッチ点を分離しての ID の割り振り処理はアプリケーションに委ねられています。 その分シンプルで非常にわかりやすい構造となっています。
iOS 3.2 からは上位 API として UIGesureRecognizer が追加されたそうです。 ( [iPhone] iPhone OS 3.2(iPad用OS)の特徴)
android 同様浮動小数値が用いられています。 タッチ点の ID 分離はない代わりに、タップ回数の判定はシステムで行ってくれます。 このあたり他の OS と違って特徴的です。
Event | Windows 7 | Android | iOS (iPhoneOS) |
---|---|---|---|
DOWN | TOUCHEVENTF_DOWN | ACTION_DOWN | touchesBegan |
UP | TOUCHEVENTF_UP | ACTION_UP | touchesEnded |
MOVE | TOUCHEVENTF_MOVE | ACTION_MOVE | touchesMoved |
CANCEL | ACTION_CANCEL | touchesCancelled |
OS | 固有 ID 割り振り | UP/DOWN イベント | マルチタップカウント | TimeStamp | 面積 | 頻度 | イベントに含まれる情報 | 補足 |
---|---|---|---|---|---|---|---|---|
Windows 7 WM_TOUCH API | あり dwID | 分離したタッチ点毎に UP/DOWN 状態が含まれる | なし | あり | あり | 選択可能 | 全部の点それぞれの詳細 | Single ならマウスとして扱える |
Android OS 2.x | あり pointerId | 個別に発生するが他の点座標も含まれる | なし | あり | あり | 低+History | 全部の点 | |
iOS (iPhoneOS) | なし(座標値から判定) | 発生した点の座標のみ単独 | あり | なし | ? | 高 | 変化した点だけ |
PRIMARY WM_TOUCH: id3 (x,y) DOWN WM_TOUCH: id3 (x,y) MOVE WM_TOUCH: id3 (x,y) MOVE id4 (x,y) DOWN WM_TOUCH: id3 (x,y) MOVE id4 (x,y) MOVE WM_TOUCH: id3 (x,y) MOVE id4 (x,y) MOVE id5 (x,y) DOWN WM_TOUCH: id3 (x,y) UP id4 (x,y) MOVE id5 (x,y) MOVE WM_TOUCH: id4 (x,y) MOVE id5 (x,y) MOVE WM_TOUCH: id4 (x,y) MOVE id5 (x,y) UP WM_TOUCH: id4 (x,y) UP
pointerIndex/pointerId (x,y) ACTION_DOWN: 0/id0 (x,y) ACTION_MOVE: 0/id0 (x,y) ACTION_MOVE: 0/id0 (x,y) ACTION_DOWN: 0/id0 (x,y) 1/id1 (x,y) actionPointerId=1 ACTION_MOVE: 0/id0 (x,y) 1/id1 (x,y) ACTION_DOWN: 0/id0 (x,y) 1/id1 (x,y) 2/id2 (x,y) actionPointerId=2 ACTION_MOVE: 0/id0 (x,y) 1/id1 (x,y) 2/id2 (x,y) ACTION_UP: 0/id0 (x,y) 1/id1 (x,y) 2/id2 (x,y) actionPointerId=0 ACTION_MOVE: 0/id1 (x,y) 1/id2 (x,y) ACTION_MOVE: 0/id1 (x,y) 1/id2 (x,y) ACTION_UP: 0/id1 (x,y) 1/id2 (x,y) actionPointerId=1 ACTION_UP: 0/id1 (x,y) actionPointerId=0
touchesBegan: (x,y) touchesMoved: (x,y) touchesMoved: (x,y) touchesBegan: (x,y) touchesMoved: (x,y) touchesMoved: (x,y) (x,y) touchesBegan: (x,y) touchesMoved: (x,y) (x,y) (x,y) touchesMoved: (x,y) (x,y) (x,y) touchesEnded: (x,y) touchesMoved: (x,y) (x,y) touchesMoved: (x,y) touchesEnded: (x,y) (x,y)
方式 | スタイラス | 指 | 爪 | 精度 | 圧力 |
---|---|---|---|---|---|
抵抗膜式 (resistive) | ◎ | △ | ◎ | ◎ | 必要 |
静電容量式 (capacitive) | × | ◎ | × | × | 不要、触れただけで反応 |
光学式 (optical) | ◎ | ◎ | ◎ | △ | 不要、触れただけで反応 |