GUI環境での強力な価値となるマウスジェスチャを.Net環境で行ってみましょう。
.NetFrameworkとC#での開発を行ったことがある方。
.NetFramework1.1以上の環境。
まずは構想を練らなければなりません。今回はサンプルなのでこちらで決めさせて頂きます。
これだけですが、一応使用に耐えうる立派なマウスジェスチャ検出になります。それと、今回は構造があまりすっきりとしていません。勘弁してください。
今回のサンプルでは一回一回の移動に対して移動量の比較を行います。何故かというと、斜めの入力を適切に処理するためです。
たとえば斜め移動を行ったときにこれをしないと二つの方向が交互に検出されてしまいます。ですのでそれを防ぐためにユーザがどちらへより動かしたかったのかを判定するのです。
32BitWindowsでは自分のウィンドウの上のマウスの動きしか知ることが出来ません。そして、.Netのアプリケーションでもそうなっているようです。そこで、「マウスのキャプチャ」を行います。
ボタンや、フォームが継承している「Control」というクラスには「bool Capture」というプロパティがあります。このプロパティをいじるとマウスをキャプチャーしたり外したり出来ます。
//マウスをキャプチャ control_.Capture = true; //マウスのキャプチャを解除 control_.Capture = false;
マウスジェスチャを検出するために次のクラスと列挙型を作ります。
namespace MouseGesture_Net { /// マウスジェスチャの判定を行う public class MouseGesture { /// 判定距離(プロパティ) public int Range /// マウスジェスチャの有効無効 private bool enable; /// 判定距離 private int range; /// 四方向それぞれについての情報(要素の大きさは4) private Direction []direction; /// マウスをキャプチャしているコントロール private Control control_; /// 移動距離計算用の古い位置 private Point old; /// コンストラクタ public MouseGesture(); /// マウスジェスチャの開始 /// <param name="control">マウスジェスチャの対象となるコントロール</param> /// <param name="pos">現在のマウス位置</param> public void Start(Control control,Point pos); /// マウスジェスチャの終わり public void End(); /// マウスジェスチャの判定 /// <param name="pos">マウスの位置</param> /// <returns>ジェスチャ</returns> public Arrow Test(Point pos); /// 4方向の情報をリセットする private void resetDirection(); #region インラインクラス /// 一定の方向に関する情報を持つ。 public class Direction { /// 有効無効 public bool Enable; /// 累計移動距離 public int Length; /// リセットします public void Reset(); /// コンストラクタ public Direction(); } #endregion } /// 方向 public enum Arrow { /// 移動無し none=-1, /// 上への移動 up=0, /// 右への移動 right=1, /// 下への移動 down=2, /// 左への移動 left=3 } }
とりあえずはこれらを実装すればちゃんとマウスジェスチャになります。
下では重点項目だけ説明してきます。
このメソッドは「MouseDown」イベントに仕掛けます。
/// <summary> /// マウスジェスチャの開始 /// </summary> /// <param name="control">マウスジェスチャの対象となるコントロール</param> /// <param name="pos">現在のマウス位置</param> public void Start(Control control,Point pos) { enable =true; resetDirection(); old =pos; control_ =control; control_.Capture =true; }
方向情報の初期化、位置のセット、コントロールから取得したウィンドウハンドルを使ってのマウスキャプチャを行います。
ここがマウスジェスチャの心臓部です。これは「MouseMove」イベントに仕掛けるのが妥当でしょう。
/// <summary> /// マウスジェスチャの判定 /// </summary> /// <param name="pos">マウスの位置</param> /// <returns>ジェスチャ</returns> public Arrow Test(Point pos) { //有効なときだけ判定する。 if(enable) { int ox = old.X ,oy = old.Y; Arrow arrow = Arrow.none; //情報を入れ替えておく old = pos; //移動量を判定して縦横どっちに動くかを判定 if(Math.Abs(ox - pos.X) > Math.Abs(oy - pos.Y)) { if(ox > pos.X) { direction[(int)Arrow.left].Length += ox - pos.X; direction[(int)Arrow.right].Length = 0; arrow = Arrow.left; } else if(pos.X >ox) { direction[(int)Arrow.right].Length += pos.X - ox; direction[(int)Arrow.left].Length = 0; arrow = Arrow.right; } } else { if(oy > pos.Y) { direction[(int)Arrow.up].Length += oy - pos.Y; direction[(int)Arrow.down].Length = 0; arrow = Arrow.up; } else if(pos.Y >oy) { direction[(int)Arrow.down].Length += pos.Y - oy; direction[(int)Arrow.up].Length = 0; arrow = Arrow.down; } } //移動を検知したとき if(arrow != Arrow.none) { if(direction[(int)arrow].Enable && direction[(int)arrow].Length > range) { resetDirection(); //同じ向きが2度入力されないようにする。 direction[(int)arrow].Enable=false; return arrow; } } } return Arrow.none; }
直感に反しないよう私なりに調整してあります。流れは次のようになります。
もっと良い工夫をお持ちの方もいると思います。色々な人に試して貰いながらどんな仕組みにするのかを決定するのが良いと思います。
ボタンが離されると、マウスキャプチャの魔法が解けてしまいます。よって、「MouseUp」イベントあたりでこのメソッドを呼ぶようにするのが妥当だと思います。
/// <summary> /// マウスジェスチャの終わり /// </summary> public void End() { if(enable) { enable =false; control_.Capture = false; } }
一応「control_.Capture」にfalseを代入しておいてください。
まずは「MouseGestureクラス」を作ってください。
そしたら、イベントの設定をします。「」のなかで「Start」を、「MOUSEMOVE」のなかで「Test」を、「BUTTONUP」のなかで「End」を呼び出すようにセットしてください。
これで「Test」を呼び出すたびに「Arrow列挙型」で値が帰ってくるようになります。
マウスジェスチャはアプリケーションに大きな魅力を付加します。使いこなせばボタンにカーソルを移動することなく素早く操作できるようになります。
是非、実装を検討してみてください。
それと、今回はサンプルなので使いやすさよりも説明のしやすさを優先させて頂きました。せっかくイベントという仕組みがあるのですからそれをしっかりと利用した方がよりよいくなると思います。