マウスジェスチャー実装
C#でフォームのコントロールなどにマウスジェスチャー機能をつけるための実装例。
MouseDown/MouseMove/MouseUpが使えるコントロールにつなげてやれば使えます。
いろいろと突っ込みどころ満載なソースなので、突っ込み歓迎です。
これを例のプログラムに追加したいけど時間がないなぁ
年末・年始にかけてできたらやっておきたい。
MouseGestureCommand.cs
using System; namespace Panda728.Utility { ////// ジェスチャーのコマンドと対応するイベントを管理する。 /// public class MouseGestureCommand { private string gesture = string.Empty; private string menuTitle = string.Empty; private EventHandler e = null; ////// 初期化 /// /// ジェスチャー /// コマンド名 /// コマンドに対応したイベント public MouseGestureCommand( string gesture, string menuTitle, EventHandler e ) { this.gesture = gesture; this.menuTitle = menuTitle; this.e = e; } ////// ジェスチャー /// public string Gesture { get { return gesture; } set { gesture = value; } } ////// コマンド名 /// public string MenuTitle { get { return menuTitle; } set { menuTitle = value; } } ////// コマンドに対応したイベント /// public EventHandler RaiseEvent { get { return e; } set { e = value; } } } }
MouseGestureManager.cs
using System; using System.Drawing; using System.Collections; namespace Panda728.Utility { ////// マウスジェスチャーのコマンド入力を管理する /// public class MouseGestureManager { // 感度 private const int MOUSE_SENSITIVITY = 4; // コマンド文字 private const string COMMAND_UP = "↑"; private const string COMMAND_DOWN = "↓"; private const string COMMAND_LEFT = "←"; private const string COMMAND_RIGHT = "→"; // 前回入力されたジェスチャー private string preArrow = ""; // 前回の位置 private Point prePos = new Point(0,0); // 入力済みのジェスチャー private System.Text.StringBuilder commands = new System.Text.StringBuilder(); // ジェスチャー判定用の命令群 private ArrayList menu = new ArrayList(); // ステータス表示用イベント private EventHandler update = null; private EventHandler refresh = null; public MouseGestureManager() { this.Refresh(); } #region properties ////// 入力済みのジェスチャー /// public string Gesture { get { return commands.ToString(); } } ////// 一致するメニューのタイトル /// public string MenuTitle { get { foreach( MouseGestureCommand m in menu ) if ( m.Gesture == commands.ToString() ) return "(" + m.MenuTitle + ")"; return string.Empty; } } ////// ジェスチャー判定用の命令群 /// public ArrayList Menu { get { return menu; } set { menu = value; } } ////// ステータス表示用イベント /// public EventHandler OnGestureCommandUpdate { get { return update; } set { update = value; } } ////// ステータスクリア /// public EventHandler OnGestureCommandRefresh { get { return refresh; } set { refresh = value; } } #endregion ////// 入力済みコマンドを初期化 /// public void Refresh() { commands.Length = 0; preArrow = ""; prePos = new Point(0,0); if ( OnGestureCommandRefresh != null) OnGestureCommandRefresh(this, new EventArgs()); } ////// ジェスチャー判定結果から処理を起動する /// public void ExecuteGesture(object sender, System.EventArgs e) { string gesture = this.Gesture; this.Refresh(); foreach( MouseGestureCommand m in menu ) { if ( m.Gesture == gesture ) { m.RaiseEvent( sender, e ); break; } } } ////// マウスが移動した場合の処理 /// public void Gesuture_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { // 初回は無効 if ( prePos.X == 0 ) { prePos = new Point(e.X, e.Y); return; } // 矢印の向きを取得 string arrow = GetArrow( e.X - prePos.X, e.Y - prePos.Y ); // 今回の位置を保持 prePos = new Point(e.X, e.Y); // 前回と同じ向きの場合は無視 if ( arrow == preArrow || arrow == string.Empty ) return; // ジェスチャー追加 commands.Append(arrow); // 今回のジェスチャーを保持 preArrow = arrow; // この辺にステータスバーへ表示する処理を追加すると便利 // (ex: StatusBar.Panels[0].Text = "ジェスチャー:" + this.Gesture + " " + this.MenuTitle;) if ( OnGestureCommandUpdate != null) OnGestureCommandUpdate( this, new EventArgs() ); } ////// 始点と終点の差異から、移動した方向を決定する /// /// 横軸の移動距離 /// 縦軸の移動距離 ///移動の向き private string GetArrow(int xDiffer, int yDiffer) { // 感度以下の動きの場合は無視 if ( Math.Abs(xDiffer) < MOUSE_SENSITIVITY && Math.Abs(yDiffer) < MOUSE_SENSITIVITY ) return string.Empty; // より縦向きにであれば縦と判定 if ( Math.Abs(xDiffer) < Math.Abs(yDiffer) && MOUSE_SENSITIVITY < Math.Abs(yDiffer) ) { // 縦方向判定 if ( yDiffer > 0 ) return COMMAND_DOWN; return COMMAND_UP; } // 横方向判定 if ( Math.Abs(xDiffer) < MOUSE_SENSITIVITY ) return string.Empty; if ( xDiffer > 0) return COMMAND_RIGHT; return COMMAND_LEFT; } } }
使用例
Form1.cs
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using Panda728.Utility; namespace MouseGesture { ////// Form1 の概要の説明です。 /// public class Form1 : System.Windows.Forms.Form { private System.Windows.Forms.StatusBar statusBar1; private System.Windows.Forms.Panel gesturePanel; ////// 必要なデザイナ変数です。 /// private System.ComponentModel.Container components = null; // MouseGesture管理クラス private MouseGestureManager gestureManager = null; public Form1() { // // Windows フォーム デザイナ サポートに必要です。 // InitializeComponent(); // マウスジェスチャーの設定 gestureManager = new MouseGestureManager(); // ジェスチャーのステータス表示 gestureManager.OnGestureCommandUpdate = new EventHandler(this.OnGestureCommandUpdate); gestureManager.OnGestureCommandRefresh = new EventHandler(this.OnGestureCommandRefresh); // 固有処理の追加 gestureManager.Menu.Add( new MouseGestureCommand( "→", "進む", new EventHandler(gestureNext_Click))); gestureManager.Menu.Add( new MouseGestureCommand( "←", "戻る", new EventHandler(gesturePrevious_Click))); gestureManager.Menu.Add( new MouseGestureCommand( "↑", "上る", new EventHandler(gestureUp_Click))); // ジェスチャーイベント登録 gesturePanel.MouseDown += new MouseEventHandler(this.gesturedControl_MouseDown); gesturePanel.MouseUp += new MouseEventHandler(this.gesturedControl_MouseUp); } ////// 使用されているリソースに後処理を実行します。 /// protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows フォーム デザイナで生成されたコード ////// デザイナ サポートに必要なメソッドです。このメソッドの内容を /// コード エディタで変更しないでください。 /// private void InitializeComponent() { this.gesturePanel = new System.Windows.Forms.Panel(); this.statusBar1 = new System.Windows.Forms.StatusBar(); this.gesturePanel.SuspendLayout(); this.SuspendLayout(); // // gesturePanel // this.gesturePanel.BackColor = System.Drawing.Color.SlateGray; this.gesturePanel.Controls.Add(this.statusBar1); this.gesturePanel.Dock = System.Windows.Forms.DockStyle.Fill; this.gesturePanel.Location = new System.Drawing.Point(0, 0); this.gesturePanel.Name = "gesturePanel"; this.gesturePanel.Size = new System.Drawing.Size(292, 273); this.gesturePanel.TabIndex = 0; // // statusBar1 // this.statusBar1.Location = new System.Drawing.Point(0, 251); this.statusBar1.Name = "statusBar1"; this.statusBar1.Size = new System.Drawing.Size(292, 22); this.statusBar1.TabIndex = 0; // // Form1 // this.AutoScaleBaseSize = new System.Drawing.Size(5, 12); this.ClientSize = new System.Drawing.Size(292, 273); this.Controls.Add(this.gesturePanel); this.Name = "Form1"; this.Text = "MouseGestureSample"; this.gesturePanel.ResumeLayout(false); this.ResumeLayout(false); } #endregion ////// アプリケーションのメイン エントリ ポイントです。 /// [STAThread] static void Main() { Application.Run(new Form1()); } #region MouseGestureControlEvents ////// ジェスチャー入力開始 /// private void gesturedControl_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e) { if ( e.Button != MouseButtons.Right ) return; gesturePanel.MouseMove += new MouseEventHandler(this.gesturedControl_MouseMove); } ////// ジェスチャー入力 /// private void gesturedControl_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e) { gestureManager.Gesuture_MouseMove( sender, e ); } ////// ジェスチャー確定 /// private void gesturedControl_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e) { if ( e.Button != MouseButtons.Right ) return; gesturePanel.MouseMove -= new MouseEventHandler(this.gesturedControl_MouseMove); // コマンド実行 gestureManager.ExecuteGesture(this, (System.EventArgs) e); } ////// 入力済みのジェスチャーを表示する /// public void OnGestureCommandUpdate(object sender, EventArgs e) { this.statusBar1.Text = "ジェスチャー:" + ((MouseGestureManager)sender).Gesture + " " + ((MouseGestureManager)sender).MenuTitle; } ////// 入力済みのジェスチャーをクリア /// public void OnGestureCommandRefresh(object sender, EventArgs e) { this.statusBar1.Text = string.Empty; } #endregion ////// 進む処理 /// public static void gestureNext_Click(object sender, System.EventArgs e) { MessageBox.Show("進むのDA!"); } ////// 戻る処理 /// public static void gesturePrevious_Click(object sender, System.EventArgs e) { MessageBox.Show("戻るのだ!"); } ////// 上る処理 /// private void gestureUp_Click(object sender, System.EventArgs e) { MessageBox.Show("上るのだ!"); } } }
C#の開発環境で、
MouseGestureManager.cs (ジェスチャー入力の管理する)
MouseGestureCommand.cs (ジェスチャーと名称とメソッドを一単位で管理)
のファイルを追加後、Form1.csの内容を上書きすれば動くはず。