[Atelier Blue アトリエブルー]HomeMemo>マウスジェスチャ(.Net版)

マウスジェスチャ(.Net版)

ダウンロード

はじめに

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;
}

直感に反しないよう私なりに調整してあります。流れは次のようになります。

  1. マウスジェスチャが有効かの判定。
  2. 縦横の移動量を判定。
  3. 左右(または上下)どちらへ移動しているのかを判定。
  4. 移動量を加算。反対への移動量を0。
  5. その移動が有効であるかを判定。
  6. 移動量が検出量に達しているかを判定。

もっと良い工夫をお持ちの方もいると思います。色々な人に試して貰いながらどんな仕組みにするのかを決定するのが良いと思います。

マウスジェスチャの終わり

ボタンが離されると、マウスキャプチャの魔法が解けてしまいます。よって、「MouseUp」イベントあたりでこのメソッドを呼ぶようにするのが妥当だと思います。

/// <summary>
/// マウスジェスチャの終わり
/// </summary>
public void End()
{
    if(enable)
    {
        enable =false;
        control_.Capture = false;
    }
}

一応「control_.Capture」にfalseを代入しておいてください。

まとめて使う

まずは「MouseGestureクラス」を作ってください。

そしたら、イベントの設定をします。「」のなかで「Start」を、「MOUSEMOVE」のなかで「Test」を、「BUTTONUP」のなかで「End」を呼び出すようにセットしてください。

これで「Test」を呼び出すたびに「Arrow列挙型」で値が帰ってくるようになります。

まとめ

マウスジェスチャはアプリケーションに大きな魅力を付加します。使いこなせばボタンにカーソルを移動することなく素早く操作できるようになります。

是非、実装を検討してみてください。

それと、今回はサンプルなので使いやすさよりも説明のしやすさを優先させて頂きました。せっかくイベントという仕組みがあるのですからそれをしっかりと利用した方がよりよいくなると思います。

参考資料


ページの一番上へ
初版2006-5-4 最終更新2006-8-5
[Atelier Blue アトリエブルー]HomeMemo>マウスジェスチャ(.Net版)