using System; using System.Collections.Generic; using System.Text; using System.Drawing; namespace Mjrk.Util.Mouse { /// /// マウスジェスチャを取得するクラス /// class MouseGesture { #region 内部変数 // 基準位置 Point? basePoint; // 方向のリスト List value = new List(); // 矢印 string[] arrows = { "", "↑", "↓", "←", "→", "[←↑]", "[→↑]", "[←↓]", "[→↓]" }; // 感度 int interval = 30; // 斜め認識 bool slant = false; // 厳密さ int strict = 3; // 厳密チェック 以前の方向 Direction strict_before; // 厳密チェック カウント int strict_count = 0; // 重複を許可 bool duplicate = false; #endregion #region プロパティ /// /// ジェスチャの内容 /// public List Value { get { return this.value; } set { this.value = value; } } /// /// ジェスチャ判定する間隔。値が少ないほど、細かい動きに反応するようになる。 /// public int Interval { get { return this.interval; } set { if (value < 1) { value = 1; } this.interval = value; } } /// /// 斜めも感知するかどうか /// public bool Slant { get { return this.slant; } set { this.slant = value; } } /// /// 厳密さ。値が高いほど、厳しく判定するようになる。 /// public int Strict { get { return this.strict; } set { if (value < 1) { value = 1; } this.strict = value; } } /// /// 重複を許可。同じ方向に長く動いた場合に重複して軌跡を記録する。 /// public bool Duplicate { get { return this.duplicate; } set { this.duplicate = value; } } #endregion #region 公開メソッド /// /// ジェスチャの記録開始 /// public void Start() { this.basePoint = null; this.value.Clear(); } /// /// ジェスチャ中に現在のポインタの位置を記録 /// /// 現在のマウスポインタの位置 public void Moving(Point point) { if (this.basePoint == null) { this.basePoint = (Point?)point; } Direction dir = this.JudgeDirection(point, (Point)this.basePoint); if (dir == Direction.None) { return; } if (this.strict_before == dir) { this.strict_count++; } else { this.strict_before = dir; this.strict_count = 0; } if (this.strict_count >= this.strict && (this.duplicate || (this.value.Count == 0 || this.value[this.value.Count - 1] != dir))) { this.value.Add(dir); this.strict_count = 0; } this.basePoint = null; } /// /// ジェスチャの文字列表現 /// /// 矢印記号で表した現在のジェスチャ public override string ToString() { StringBuilder strb = new StringBuilder(); foreach (Direction d in this.value) { strb.Append(this.arrows[(int)d]); } return strb.ToString(); } #endregion #region 非公開メソッド /// /// 方向を判断 /// /// 現在のポインタの位置 /// 基準となるポインタの位置 /// 方向 protected Direction JudgeDirection(Point a, Point b) { if ((int)(Math.Sqrt(Math.Pow(Math.Abs(a.X - b.X), 2) + Math.Pow(Math.Abs(a.Y - b.Y), 2))) < this.Interval / this.Strict) { return Direction.None; } double dir = Math.Abs(a.X - b.X) / (Math.Abs(a.Y - b.Y) + 0.0001); if (this.Slant && dir > 0.4 && dir < 1.6) { if (a.X > b.X) { if (a.Y > b.Y) { return Direction.BottomRight; } else { return Direction.TopRight; } } else { if (a.Y > b.Y) { return Direction.BottomLeft; } else { return Direction.TopLeft; } } } if (dir > 1) { if (a.X > b.X) { return Direction.Right; } else { return Direction.Left; } } else { if (a.Y > b.Y) { return Direction.Bottom; } else { return Direction.Top; } } } #endregion } /// /// 方向を表す列挙型 /// public enum Direction { /// /// 無指向 /// None = 0, /// /// 上方向 /// Top = 1, /// /// 下方向 /// Bottom = 2, /// /// 左方向 /// Left = 3, /// /// 右方向 /// Right = 4, /// /// 左上 /// TopLeft = 5, /// /// 右上 /// TopRight = 6, /// /// 左下 /// BottomLeft = 7, /// /// 右下 /// BottomRight = 8 } }