コントロールに簡単にマウスジェスチャを実装出来る。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();
}
}
}
This program is wonderful! be moved!
Thanks for the try!