はじめに
私はGUI環境で簡単にコマンドを送ることができるマウスジェスチャが大好きです。今回はそんなマウスジェスチャを作ってみましょう。なお、.NET版については別稿を参照してください。
対象読者
C言語(またはC++言語)でWin32のプログラムを開発したことがある方。
必要な環境
少なくとも32bitのWindows環境が必要です。64bit環境でのテストはしていませんが大丈夫だと思います。
設計
まずは構想を練らなければなりません。今回はサンプルなのでこちらで決めさせて頂きます。
- 右ボタンが押されたら始まり、離されたら終わる。
- 入力可能方向は4方向(斜め判定は無し)
- 同じ方向への連続入力は無し(普通はこうすると思います)
- ある方向に動かすと反対側の移動量は0になる
- 縦横の移動量を比較して多い方だけを考える(より自然な移動になる)
- ウィンドウの外に出てもしっかりと動作するようにする(これを行わないと変なことになる)
これだけですが、一応使用に耐えうる立派なマウスジェスチャ検出になります。
例えば斜め移動を行ったときに、これを行わないと2つの方向が交互に検出されてしまいます。それを防ぐためにユーザーがどちらへより動かしたかったのかを判定します。
必要になるAPI
今回重要な役割を果たすのが次のAPIです。
書式 | 説明 |
HWND SetCapture(HWND hWnd); |
マウスが押されている間、カーソルの動きを追跡(マウスをキャプチャ) |
BOOL ReleaseCapture(VOID); |
上の動作を取り消し(キャプチャ取り消し) |
32bit Windowsではマウスについてのイベントが厳しくなっています。
まず第一に、自分のウィンドウの上のマウスの動きしか知ることができません。.NETのアプリケーションでもそうなっているようです。そこで、「マウスのキャプチャ」を行います。マウスのキャプチャを行うと、自分だけにマウスの動きが教えられ続けます。
ただしこれにも制限があって、自分のウィンドウ内で押されたマウスが、押され続けている間だけ有効です。
これらの条件は厳しいですが、今回マウスジェスチャを行う上ではちょうど良いくらいの機能です。ちなみにキャプチャされた移動と、ボタンを放す動作は「WM_~」としてウィンドウプロシージャに送られてきます。
データ構造
マウスジェスチャを検出するために作る構造体です。C++であればクラスにまとめるのがベストかと思いますが、C言語との相互運用を考えて今回は構造体です。
//方向を表す列挙型 typedef enum tag_MGARROW{ MG_NONE = -1, //移動無し MG_UP = 0, //上に移動 MG_RIGHT =1, //右に移動 MG_DOWN = 2, //下に移動 MG_LEFT = 3 //左に移動 }MGARROW; //それぞれの方向への情報を持つ typedef struct tag_MGDIRECTION{ BOOL enable; //有効か? int length; //累計移動距離 }MGDIRECTION; //マウスジェスチャを行うための要の構造体 typedef struct tag_MOUSEGESTURE { BOOL enable; //有効か? int range; //判定距離 MGDIRECTION direc[4];//それぞれの方向の情報 //添え字の番号は「MGARROW」と対応する POINT old; //移動距離を出すための位置 }MOUSEGESTURE;
それぞれの方向に有効判定を付けたのは2連続を防止するためです。「int range
」は「移動した」と判断するのに必要な距離です。「POINT old
」は前回に判定を行った位置です。その位置を起点にして累計移動量を出していきます。