Hello Stoitcho,
Thanks for the information. I have written an inheritable panel in which I've implemented the Click, SingleClick and DoubleClick
logic. Since I presume the the DoubleClick in the framework is already taking the metrics you described into account I am
concluding that if a double click doesn't occur within SystemInformation.DoubleClickTime interval then I have a SingleClick. This
makes it fairly trivial to determine if a click is Single or Double.
If you want an application to take actions on click and double click you
should design your application in a fashion where double click action is a
complement of the single click one.
For example single-click - selectes and double-click executes (or take some
action over the selected objects)
After using my class and understanding that the timing involved in a double-click is sytem dependant I wholeheartedly agree with
your statement above. Wherever both single and double clicks are allowed the click event needs to be used where it can be repeated
over and over again. The way I've implemented the SingleClick event has the side-effect of the DoubleClick actually being handled
quicker than a SingleClick. This is because the SingleClick event can't be fired until the timeout for the DoubleClick has elapsed.
Depending on how a user configured their mouse in the control panel that could be a long or short time and when on the long side may
not give the desired result as far as UI is concerned.
Thanks much for the information and comments. I really appreciate your input.
Sincerely,
Gregg Walker
p.s. Here's the code for my base class panel. Let me know if you have any comments.
using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using Rmca.Common;
namespace Rmca.Forms
{
/// <summary>
/// Summary description for EntryPanel.
/// </summary>
public class EntryPanel : System.Windows.Forms.Panel
{
public event System.EventHandler SingleClick;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
private System.Timers.Timer _clickTimer = null;
private bool _clickFired = false;
private bool _clickTimerFired = false;
public EntryPanel()
{
// This call is required by the Windows.Forms Form Designer.
InitializeComponent();
// TODO: Add any initialization after the InitComponent call
_clickTimer = new System.Timers.Timer(SystemInformation.DoubleClickTime);
_clickTimer.Enabled = false;
_clickTimer.Elapsed += new System.Timers.ElapsedEventHandler(_clickTimer_Elapsed);
_clickTimer.SynchronizingObject = this;
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if( components != null )
components.Dispose();
}
if(_clickTimer != null)
{
_clickTimer.Stop();
_clickTimer.Dispose();
_clickTimer = null;
}
base.Dispose( disposing );
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
protected override void OnPaint(PaintEventArgs pe)
{
// TODO: Add custom paint code here
// Calling the base class OnPaint
base.OnPaint(pe);
}
protected override void OnClick(EventArgs e)
{
_clickFired = true;
base.OnClick(e);
}
protected virtual void OnSingleClick(System.EventArgs e)
{
if(_clickTimer != null)
{
if(_clickTimer.Enabled)
{
_clickTimer.Stop();
_clickTimerFired = false;
}
}
if(this.SingleClick != null)
{
this.SingleClick(this, e);
}
}
protected override void OnDoubleClick(EventArgs e)
{
if(_clickTimer != null)
{
if(_clickTimer.Enabled)
{
_clickTimer.Stop();
_clickTimerFired = false;
}
}
base.OnDoubleClick(e);
}
protected override void OnMouseDown(MouseEventArgs e)
{
base.OnMouseDown(e);
if(_clickTimer != null)
{
if(this.SingleClick != null)
{
_clickFired = false;
_clickTimerFired = false;
if(e.Clicks < 2)
{
_clickTimer.Start();
}
else
{
_clickTimer.Stop();
_clickTimerFired = false;
}
}
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
base.OnMouseUp(e);
if(_clickTimer != null)
{
if(_clickTimerFired)
{
PerformSingleClick();
}
}
}
private void _clickTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if(_clickTimer != null)
{
_clickTimer.Stop();
_clickTimerFired = true;
if(_clickFired)
{
PerformSingleClick();
}
}
}
protected virtual void PerformClick()
{
this.OnClick(new System.EventArgs());
}
protected virtual void PerformSingleClick()
{
this.OnSingleClick(new System.EventArgs());
}
protected virtual void PerformDoubleClick()
{
this.OnDoubleClick(new System.EventArgs());
}
}
}