We help IT Professionals succeed at work.

Click, Double Click and Triple Click

AlHal2
AlHal2 asked
on
152 Views
Last Modified: 2018-09-13
How does C# distinguish between two single click events and a double click event?
Suppose I have a key and I want it to display "1" in the textbox if pressed once; "2" in the textbox if pressed twice and "3" if pressed three times.
If the gap between key presses is more than a second reset counter to zero.
Comment
Watch Question

it_saigeDeveloper
CERTIFIED EXPERT
Distinguished Expert 2019
Commented:
This problem has been solved!
(Unlock this solution with a 7-day Free Trial)
UNLOCK SOLUTION
Russ SuterSenior Software Developer
CERTIFIED EXPERT

Commented:
It's determined by the operating system. There's an option in the Mouse Properties control panel that lets you adjust the double click speed.
Mouse Control PanelThe OS will always send a click event message on a single click. If another click is registered before the interval has elapsed (and that click is within a given distance from the first click) it will send an double click message as well. If the second click is registered after the time has elapsed then you just get another single click event.

As it_saige suggested above, you can hook into the windows messaging system and create your own handler to simulate a double-click event using timing other than what the operating system uses.
AndyAinscowFreelance programmer / Consultant
CERTIFIED EXPERT

Commented:
In addition it is considered really bad practice to modify system settings without asking the user first - so adjusting the double click interval in the operating system by your app should not be an option.

The op system does not recognise a triple click, that is something you have to do yourself.

A simple alternative to that above is for your app to have the same handler for a double click as for a single click and you track the interval between mouse click events yourself and act appropriately.

Author

Commented:
Hi IT_Saige,

I've no doubt that your hook will work.  The only problem is my difficulty understanding it.
Why do you need to call DLLs?
Perhaps the complexity is due to the requestor asking about co-ordinates.  Do you have a version which just does what I need?
The code below doesn't work properly with an old mobile keypad.  I'm trying to see if it's a simple bug in my code or if I'm missing something more fundamental.

public Button clickedButton1 = null;
        public Button clickedButton2 = null;
        public Button clickedButton3 = null;
        public Button clickedButton4 = null;
        public DateTime clickTime1 = new DateTime(2011,1,1,1,1,1,1);
        public DateTime clickTime2 = new DateTime(2011, 1, 1, 1, 1, 1, 1);
        public DateTime clickTime3 = new DateTime(2011, 1, 1, 1, 1, 1, 1);
        public DateTime clickTime4 = new DateTime(2011, 1, 1, 1, 1, 1, 1);
        TimeSpan timeDiff1;
        TimeSpan timeDiff2;
        TimeSpan timeDiff3;
        TimeSpan timeDiff1Now;
        TimeSpan timeDiff2Now;
        public string LetterToDisplay = "";
        public int cmdAbcPressed = 0;
        public int cmdDefPressed = 0;
private void ProcessButton(object sender, EventArgs e)
        {

            clickedButton4 = clickedButton3;
            clickTime4 = clickTime3;
            clickedButton3 = clickedButton2;
            clickTime3 = clickTime2;
            clickedButton2 = clickedButton1;
            clickTime2 = clickTime1;
            clickedButton1 = sender as Button;
            clickTime1 = DateTime.Now;

            timeDiff1 = clickTime1-clickTime2;
            timeDiff2 = clickTime2 - clickTime3;
            timeDiff3 = clickTime3 - clickTime4;

            timeDiff1Now = DateTime.Now-clickTime2;
            timeDiff2Now = DateTime.Now - clickTime3;
            //MessageBox.Show(clickedButton1.Name + " clicked at " + clickTime1);
        }

        private void cmdAbc_Click(object sender, EventArgs e)
        {
            //string LetterToDisplay = "";
            cmdAbcPressed += 1;
            cmdDefPressed = 0;
            //if (LetterToDisplay!="")
            //{
            //    DisplayText(LetterToDisplay);
            //}
            ProcessButton(sender,e);
            if (clickedButton2 == null)
            {
                LetterToDisplay = "a";
            }
            else if(clickedButton2 != clickedButton1)
            {
                LetterToDisplay = "a";
            }
            else if  (timeDiff1.TotalMilliseconds > 500)
                //else if (((clickTime1 - clickTime2).Milliseconds > 500))
            {
                LetterToDisplay = "a";
            }
            else
            {
                if (clickedButton3 == null)
                {
                    LetterToDisplay = "b";
                }
                else if (clickedButton3 != clickedButton2)
                {
                    LetterToDisplay = "b";
                }
                else if (timeDiff2.TotalMilliseconds > 500)
                //else if (((clickTime2 - clickTime3).Milliseconds > 500))

                {
                    LetterToDisplay = "b";
                }
                else
                {
                    LetterToDisplay = "c";
                }
            }
  
            DisplayText(LetterToDisplay);
            txtDebug.Text = txtDebug.Text + (timeDiff1.TotalMilliseconds + " | " + timeDiff2.TotalMilliseconds + " | " + clickTime1 + " | " + clickTime2 + " | " + clickTime3 + " | " + clickTime4 + (char)13 + (char)10);
            if (clickedButton3 != null)
            {
                if ((timeDiff2Now).TotalMilliseconds > 500)
                {
                    clickedButton1 = null;
                    clickedButton2 = null;
                    clickedButton3 = null;
                    clickTime3 = new DateTime(2011, 1, 1, 1, 1, 1, 1);
                    clickTime2 = new DateTime(2011, 1, 1, 1, 1, 1, 1);
                    clickTime1 = new DateTime(2011, 1, 1, 1, 1, 1, 1);
                }
            }
            if (clickedButton2 != null)
            {
                if ((timeDiff1Now).TotalMilliseconds > 500)
                {
                    clickedButton1 = null;
                    clickedButton2 = null;
                    clickTime2 = new DateTime(2011, 1, 1, 1, 1, 1, 1);
                    clickTime1 = new DateTime(2011, 1, 1, 1, 1, 1, 1);
                }
            }
            if (clickedButton1 != null)
            {
                if ((DateTime.Now - clickTime1).TotalMilliseconds > 500)
                {
                    clickedButton1 = null;
                    clickTime1 = new DateTime(2011, 1, 1, 1, 1, 1, 1);
                }
            }

        }

Open in new window

Senior Software Developer
CERTIFIED EXPERT
Commented:
This problem has been solved!
(Unlock this solution with a 7-day Free Trial)
UNLOCK SOLUTION

Author

Commented:
I've put Saige's solution into program.cs in a windows form application.
I want to put two buttons onto Form1 and check their click, double click and triple click events.  Also, I need to see if the user has pressed button 2 after a single or double click of button 1.
What do I put in form1.cs?
Russ SuterSenior Software Developer
CERTIFIED EXPERT

Commented:
AlHal2,

Where are you on this issue? Do you still need help?

Author

Commented:
I realised I could use key presses instead of mouse clicks and came up with this code.  It seems to work, but let me know what you think.


using System;

using System.Text.RegularExpressions;
using System.Windows.Forms;
using System.IO;
namespace 
{
    public partial class Form1 : Form
    {
        public DateTime FirstClickTime = new DateTime(2011, 1, 1, 1, 1, 1, 1);
        public DateTime SecondClickTime = new DateTime(2011, 1, 1, 1, 1, 1, 1);
        public DateTime ThirdClickTime = new DateTime(2011, 1, 1, 1, 1, 1, 1);
        public DateTime FourthClickTime = new DateTime(2011, 1, 1, 1, 1, 1, 1);
        TimeSpan timeDiff1;
        TimeSpan timeDiff2;
        TimeSpan timeDiff3;
        TimeSpan timeDiff1Now;
        public string FirstKey = "";
        public string SecondKey = "";
        public string ThirdKey = "";
        public string FourthKey = "";
        public DateTime StartTime;
        public DateTime EndTime;
        public int Keystrokes = 0;
        public int TimeTaken = 0;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            StartTime = DateTime.Now;
            using (StreamWriter sw = new StreamWriter(@"D:\OneDrive\Documents\Tests\OldMobileKeyboard\MobKeyboard4\Results.txt", false))
            {
                sw.WriteLine("Started at " + StartTime);
            }
        }
        private void textBox1_KeyUp(object sender, KeyEventArgs e)
        {
            textBox1.Text = Regex.Replace(textBox1.Text, @"[\d-]", "");
            textBox1.Text = textBox1.Text.Replace("?", "");
        }
        private string ReturnKeys(string KeyPressed)
        {
            
            string OutputKey = "";
            switch (KeyPressed)
            {
                case "2":
                    OutputKey = "abc";
                    break;

                case "3":
                    OutputKey = "def";
                    break;
                case "4":
                    OutputKey = "ghi";
                    break;
                case "5":
                    OutputKey = "jkl";
                    break;
                case "6":
                    OutputKey = "mno";
                    break;
                case "7":
                    OutputKey = "pqrs";
                    break;
                case "8":
                    OutputKey = "tuv";
                    break;
                case "9":
                    OutputKey = "wxyz";
                    break;
                case "0":
                    OutputKey = " ";
                    break;
                case "#":
                    OutputKey = "#";
                    break;
                case "*":
                    OutputKey = "*";
                    break;

                default:
                    OutputKey = "???";
                    MessageBox.Show("Please enter one of the following keys: 234567890*#");
                    break;
            }
                    return OutputKey;
            
        }

        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            
            try
            {
                using (StreamWriter sw = new StreamWriter(@"D:\OneDrive\Documents\Tests\OldMobileKeyboard\MobKeyboard4\Results.txt", true))
                {
                Keystrokes += 1;
                textBox1.Text = Regex.Replace(textBox1.Text, @"[\d-]", "");
                textBox1.Text = textBox1.Text.Replace("?", "");
                FourthKey = ThirdKey;
                FourthClickTime = ThirdClickTime;
                ThirdKey = SecondKey;
                ThirdClickTime = SecondClickTime;
                SecondKey = FirstKey;
                SecondClickTime = FirstClickTime;
                FirstKey = e.KeyChar.ToString();
                FirstClickTime = DateTime.Now;
                string LetterToDisplay = "";
                timeDiff1Now = DateTime.Now - FirstClickTime;
                timeDiff1 = FirstClickTime - SecondClickTime;
                timeDiff2 = SecondClickTime - ThirdClickTime;
                timeDiff3 = ThirdClickTime - FourthClickTime;
                int NumberOfClicks = 0;
                
                    switch (FirstKey)
                    {
                        case ("2"):
                        case ("3"):
                        case ("4"):
                        case ("5"):
                        case ("6"):
                        case ("7"):
                        case ("8"):
                        case ("9"):
                        case ("0"):
                        case ("*"):
                        case ("#"):
                            break;
                        default:
                            e.Handled = true;
                            break;
                    }
                if (FirstKey != SecondKey)
                {
 
                        LetterToDisplay = ReturnKeys(FirstKey).Substring(0, 1);
                        NumberOfClicks = 1;
                        TimeTaken += 500;

                }
                else if (FirstKey == SecondKey && timeDiff1.TotalMilliseconds >= 500)
                {
                    LetterToDisplay = ReturnKeys(FirstKey).Substring(0, 1);
                    NumberOfClicks = 1;
                    TimeTaken += 500;
                    }
                else if (SecondKey == ThirdKey && timeDiff2.TotalMilliseconds < 500 && ThirdKey == FourthKey && timeDiff3.TotalMilliseconds >= 500)
                {
                    LetterToDisplay = ReturnKeys(SecondKey).Substring(2, 1);
                    NumberOfClicks = 3;
                    TimeTaken += 500;
                    }
                else if (SecondKey == ThirdKey && timeDiff2.TotalMilliseconds < 500 && ThirdKey == FourthKey && timeDiff3.TotalMilliseconds < 500)
                {
                    LetterToDisplay = ReturnKeys(SecondKey).Substring(3, 1);
                    NumberOfClicks = 4;
                    TimeTaken += 100;
                    }
                else if (FirstKey == SecondKey && timeDiff1.TotalMilliseconds < 500 && SecondKey != ThirdKey)
                {
                    LetterToDisplay = ReturnKeys(FirstKey).Substring(1, 1);
                    NumberOfClicks = 2;
                    TimeTaken += 100;
                }
                else if (FirstKey == SecondKey && timeDiff1.TotalMilliseconds < 500 && SecondKey == ThirdKey && timeDiff2.TotalMilliseconds >= 500)
                {
                    LetterToDisplay = ReturnKeys(FirstKey).Substring(1, 1);
                    NumberOfClicks =2;
                    TimeTaken += 100;
                }
                else if (FirstKey == SecondKey && timeDiff1.TotalMilliseconds < 500 && SecondKey == ThirdKey && timeDiff2.TotalMilliseconds < 500)
                {
                    LetterToDisplay = ReturnKeys(FirstKey).Substring(2, 1);
                    NumberOfClicks = 3;
                    TimeTaken += 100;
                }
                else
                {
                    LetterToDisplay = ReturnKeys(FirstKey).Substring(0, 1);
                    NumberOfClicks = 1;
                    TimeTaken += 500;
                }

                if (NumberOfClicks >1)
                {
                    textBox1.Text = textBox1.Text.Remove(textBox1.Text.Length -  1,  1);
                }
                
                textBox1.Text = textBox1.Text + LetterToDisplay;
                sw.WriteLine(e.KeyChar);
                textBox1.Text= Regex.Replace(textBox1.Text, @"[\d-]", "");
                textBox1.Text = textBox1.Text.Replace("?", "");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            EndTime = DateTime.Now;
            using (StreamWriter sw = new StreamWriter(@"D:\OneDrive\Documents\Tests\OldMobileKeyboard\MobKeyboard4\Results.txt", true))
            {
                sw.WriteLine("Ended at   " + EndTime);
                sw.WriteLine("Duration" + (EndTime - StartTime));
                sw.WriteLine("Minimum Duration " + TimeTaken +" milliseconds");
                sw.WriteLine("keystrokes " + (Keystrokes));
                sw.WriteLine("To make this more configurable I would put each key in a cross reference file with the chracters assigned to it.");
            }
            Environment.Exit(0);
        }
    }
}

Open in new window

Russ SuterSenior Software Developer
CERTIFIED EXPERT

Commented:
I'm not sure what you're trying to accomplish here but it's a completely different problem than your initial question. May I suggest that if you require assistance with the code immediately above that you open a new question. As for the original question about single, double, and triple clicking, both it_saige and myself offered viable solutions.

Author

Commented:
Thanks all.

Gain unlimited access to on-demand training courses with an Experts Exchange subscription.

Get Access
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Empower Your Career
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE

Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions