Windowsフォームで、マウスダウンとダブルクリックで処理を分けたくなることがある。
このとき、OnMouseDownとOnMouseDoubleClickにそれぞれ処理を書けば良いのでは・・・という考えが始めに浮かぶのだが、そう単純には行かない。
この問題について見てみよう。
マウスボタンを一回クリックしたときのイベントは次のような順序で発生する。
1.MouseDown
2.Click
3.MouseClick
4.MouseUp
また、マウスボタンをダブルクリックしたときは次のような順序でイベントが発生する。
1.MouseDown
2.Click
3.MouseClick
4.MouseUp
5.MouseDown
6.DoubleClick
7.MouseDoubleClick
8.MouseUp
このように、MouseDownイベントは常に発生する。そして、ダブルクリックがある場合はMouseDownが起きた後、MouseDoubleClickイベントが発生している。
つまり、始めに思い浮かんだ方法だと、ダブルクリックをしようがしまいがMouseDownのイベントに書いた処理は実行されてしまう。ここを何とかして、ダブルクリックしたときはMouseDownの処理をスキップするようにしたい。
これを実現するために、System.Windows.Forms.Timerを使う方法がある。
以下にサンプルコードを示す。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace MouseDownAndDoubleClick { public partial class Form1 : Form { private Timer timer = new Timer() { Enabled = false }; public Form1() { InitializeComponent(); timer.Tick += (sender, args) => { // タイマーを止める timer.Enabled = false; timer.Stop(); // マウスダウンの処理をここで行う Console.WriteLine("Do MouseDown Process.."); }; } /// <summary> /// マウスダウン /// </summary> /// <param name="e"></param> protected override void OnMouseDown(MouseEventArgs e) { Console.WriteLine("-MouseDown-"); // タイマー開始 timer.Enabled = true; // システムに設定されたダブルクリックの判定時間間隔を取得 timer.Interval = SystemInformation.DoubleClickTime; timer.Start(); base.OnMouseDown(e); } /// <summary> /// マウスダブルクリック /// </summary> /// <param name="e"></param> protected override void OnMouseDoubleClick(MouseEventArgs e) { // タイマー停止 if (timer.Enabled) { timer.Enabled = false; timer.Stop(); } // ダブルクリックの処理をここで行う Console.WriteLine("Do MouseDoubleClick process.."); base.OnMouseDoubleClick(e); } } }
まず、マウスダウンが起きたときの処理を見てみよう。その処理は35行目からのメソッドである。
あらかじめ用意してあるタイマーに、システムで設定したダブルクリック判定時間を設定する。
ダブルクリック判定時間というのは、その時間内に複数回マウスクリックがあったとき、それをダブルクリックと判定する時間のことである。
時間を設定したらタイマーを起動する。
タイマーの処理は22行目に書いてある。設定時間になったら本来マウスダウンのタイミングで行う処理をここで行うようにする。
次に、ダブルクリック時の処理を見てみよう。その処理は51行目からのメソッドである。
ダブルクリックが起きたときは、タイマーを止めてダブルクリックのタイミングで行いたい処理を行う。
プログラムを実行すると以下のようにコンソールに出力される。
1.マウスダウンを1回行ったとき
-MouseDown-
Do MouseDown Process..
2.ダブルクリックしたとき
-MouseDown-
-MouseDown-
Do MouseDoubleClick process..
このようにして、マウスダウンのタイミングで行いたい処理をタイマーで遅らせることによって、それぞれ処理を分けることができる。
ただし、システムのダブルクリック判定時間の設定値にもよるが、マウスダウン時の処理は直接書いた場合と比べて体感できるほどの遅れが発生してしまう。
そのため場合によっては使えないケースもあるだろう。