C#|Control|マウスジェスチャを実装する

コントロールに簡単にマウスジェスチャを実装出来る。WebBrowserコントロールには使えない。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace Anis.Controls {
    ///<summary>コントロールにマウスジェスチャ機能を追加するクラス</summary>
    public class MouseGestureListener :IDisposable {
        Control ctrl;
        ToolStripStatusLabel statusView;
        int sensitivity;
        string gestureStatus;
        Dictionary<string, string> actionList;
        Point mousePosition;
        bool contextMenuEnabled;
        bool isMouseDown = false;
        ContextMenuEnabledChange contextMenuEnabledChange;

        /// <param name="ctrl">マウスジェスチャ機能を追加するコントロール</param>
        /// <param name="sensitivity">マウスジェスチャの感度</param>
        /// <param name="statusToolStripItem">マウスジェスチャの状態を表示させるToolStripItem</param>
        /// <param name="actionList">キーに"↑","→","↓","←",を組み合わせたマウスジェスチャを、
        /// 値にアクション名を登録したDictionary</param>
        /// <param name="contextMenuEnabledChange">コンテキストメニューの有効無効を切り替えるためのメソッド</param>
        /// <param name="contextMenuEnabled">コンテキストメニューの有効、無効</param>
        ///<remarks>マウスジェスチャが完了するとGestureCompleteイベントが発生するので、
        /// e.Actionでアクション名を取得して下さい。</remarks>
        public MouseGestureListener(
            Control ctrl,
            ToolStripStatusLabel statusView,
            int sensitivity,
            Dictionary<string, string> actionList,
            ContextMenuEnabledChange contextMenuEnabledChange,
            bool contextMenuEnabled) {

            this.ctrl = ctrl;
            this.sensitivity = sensitivity;
            this.statusView = statusView;
            this.actionList = actionList;
            this.contextMenuEnabledChange = contextMenuEnabledChange;
            this.contextMenuEnabled = contextMenuEnabled;

            statusView.TextChanged += new EventHandler(statusToolStripItem_TextChanged);
            ctrl.MouseDown += new MouseEventHandler(ctrl_MouseDown);
            ctrl.MouseMove += new MouseEventHandler(ctrl_MouseMove);
            ctrl.MouseUp += new MouseEventHandler(ctrl_MouseUp);
            ctrl.PreviewKeyDown += new PreviewKeyDownEventHandler(ctrl_PreviewKeyDown);
        }

        void ctrl_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e) {
            contextMenuEnabledChange(contextMenuEnabled);
        }

        void ctrl_MouseUp(object sender, MouseEventArgs e) {
            if(actionList.ContainsKey(gestureStatus)) {
                GestureComplete(sender, new GestureCompleteEventArgs(actionList[gestureStatus]));
            }
            isMouseDown = false;
            gestureStatus = "";
            statusView.Text = "";
        }

        void ctrl_MouseMove(object sender, MouseEventArgs e) {
            if(gestureStatus == "") {
                contextMenuEnabledChange(contextMenuEnabled);
            }
            if(Control.MouseButtons != MouseButtons.Right) {
                isMouseDown = false;
                statusView.Text = "";
                gestureStatus = "";
            }
            if(isMouseDown) {
                string str = "";
                bool flag = false;
                if(mousePosition.X - e.Location.X >= sensitivity && !gestureStatus.EndsWith("←")) {
                    str = "←";
                    flag = true;
                } else if(mousePosition.X - e.Location.X <= -sensitivity && !gestureStatus.EndsWith("→")) {
                    str = "→";
                    flag = true;
                } else if(mousePosition.Y - e.Location.Y >= sensitivity && !gestureStatus.EndsWith("↑")) {
                    str = "↑";
                    flag = true;
                } else if(mousePosition.Y - e.Location.Y <= -sensitivity && !gestureStatus.EndsWith("↓")) {
                    str = "↓";
                    flag = true;
                }
                if(flag) {
                    mousePosition = e.Location;
                    gestureStatus += str;
                    statusView.Text = gestureStatus;
                    contextMenuEnabledChange(false);
                }
            }
        }

        void ctrl_MouseDown(object sender, MouseEventArgs e) {
            if(Control.MouseButtons == MouseButtons.Right) {
                mousePosition = e.Location;
                gestureStatus = "";
                isMouseDown = true;
            }
        }

        void statusToolStripItem_TextChanged(object sender, EventArgs e) {
            ToolStripItem ctrl = (ToolStripItem)sender;
            if(actionList.ContainsKey(ctrl.Text)) {
                ctrl.Text += "[" + actionList[ctrl.Text] + "]";
            }
        }

        /// <summary>マウスジェスチャが完了すると発生するイベント</summary>
        public event GestureCompleteEventHandler GestureComplete;

        #region IDisposable メンバ

        public void Dispose() {
            statusView.TextChanged -= new EventHandler(statusToolStripItem_TextChanged);
            ctrl.MouseDown -= new MouseEventHandler(ctrl_MouseDown);
            ctrl.MouseMove -= new MouseEventHandler(ctrl_MouseMove);
            ctrl.MouseUp -= new MouseEventHandler(ctrl_MouseUp);
            ctrl.PreviewKeyDown -= new PreviewKeyDownEventHandler(ctrl_PreviewKeyDown);
        }

        #endregion
    }

    ///<summary>GestureCompleteイベントを処理するメソッドを表します。</summary>
    public delegate void GestureCompleteEventHandler(object sender, GestureCompleteEventArgs e);

    /// <summary>コンテキストメニューの有効、無効を切り替えるメソッドを表します。</summary>
    public delegate void ContextMenuEnabledChange(bool contextMenuEnabled);

    /// <summary>GestureCompleteイベントのデータ</summary>
    public class GestureCompleteEventArgs :EventArgs {
        private string action_ = "";
        /// <param name="action">マウスジェスチャのアクション名</param>
        public GestureCompleteEventArgs(string action)
            : base() {
            action_ = action;
        }
        /// <summary>マウスジェスチャのアクション名を取得します。</summary>
        public string Action {
            get { return action_; }
        }
    }
}

 

以下の様に使用する。

using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Anis.Controls;
namespace WindowsFormsApplication1 {
    public partial class Form1 :Form {
        public Form1() {
            InitializeComponent();
        }
        MouseGestureListener mgl;

        private void Form1_Load(object sender, EventArgs e) {
                        Dictionary<string, string> gestureList = new Dictionary<string, string>();
            gestureList.Add("↓→↓", "閉じる");
                        mgl = new MouseGestureListener(
                this.textBox1,                 this.toolStripStatusLabel1,15,                  gestureList,                 contextEnabledChange,                 this.textBox1.ShortcutsEnabled);

            mgl.GestureComplete += new GestureCompleteEventHandler(mgl_GestureComplete);
        }
        void mgl_GestureComplete(object sender, GestureCompleteEventArgs e) {
            if(e.Action == "閉じる") {
                this.Close();
            }
        }

        private void contextEnabledChange(bool value) {
            this.textBox1.ShortcutsEnabled = value;
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
            mgl.Dispose();
        }
    }
}

 

2 thoughts on “C#|Control|マウスジェスチャを実装する

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください