Triple Mouse Click in C#?
Asked Answered
D

6

10

In MS-Word Mouse Click events are used as:

Single Click - placing Cursor
Double Click - Selects Word
Triple Click - Selects Paragraph

In C# I can handle single and double mouse click events but I want to handle a Triple Mouse Click event in C# Windows TextBox.

Example:

void textbox1_TripleClick()
{
    MessageBox.Show("Triple Clicked"); 
} 
Delija answered 16/2, 2011 at 9:43 Comment(0)
K
8

Have a look at this: Mousebuttoneventargs.clickcount

That should cover it I suppose.

Kea answered 16/2, 2011 at 9:50 Comment(2)
For Windows Forms (rather than WPF) he'd probably want the very similar MouseEventArgs.ClickCount property: msdn.microsoft.com/en-us/library/…Lauren
... Except that it doesn't work in Winforms. In a TextBox at least, ClickCount only ever returns 1... even on a double-click!Lauren
G
6

DO THIS:

    private int _clicks = 0;
    private System.Windows.Forms.Timer _timer = new System.Windows.Forms.Timer();
    private void txtTextMessage_MouseUp(object sender, MouseEventArgs e)
    {
        _timer.Stop();
        _clicks++;
        if (_clicks == 3)
        {
            // this means the trip click happened - do something
            txtTextMessage.SelectAll();
            _clicks = 0;
        }
        if (_clicks < 3)
        {
            _timer.Interval = 500;
            _timer.Start();
            _timer.Tick += (s, t) =>
            {
                _timer.Stop();
                _clicks = 0;
            };
        }
    }
Gobetween answered 26/5, 2017 at 18:20 Comment(1)
I love code that just drops in and works. +1. Thanks!Revive
B
2

You just have to store the time when a double click occured in that Box. Then, in the handler for the single click, check if a double click happened not more than N milliseconds ago (N = 300 or so).

In this case, call your TripleClick() function directly or define a new event for you derived "TripleClickAwareTextBox".

Bise answered 16/2, 2011 at 9:48 Comment(2)
Don't guess a time that's going to be too short for some users, too long for others. Use the time that the user has configured in their OS as their preferred double click time. It's accessible through SystemInformation.DoubleClickTime - msdn.microsoft.com/en-us/library/…Verena
You also want to make sure each click occurs within a bounding box of the last click, with size SystemInformation.DoubleClickSize.Lauren
P
2

I was working on a similar issue on C++

Firstly, you need to understand how the events are fired, i 'll take click using the left mouse button: - Click once -> Left button click event fired - Double click -> Left double click event fired

Windows only support you up to this level.

For triple click, it's essentially a click following a double click with the in-between time small enough. So, what you need to do is handle a click event, check if there was a double click before that and fire a triple click event.

Though the code is different, this is how I do it:

  • Declare doubleClickTime & doubleClickInterval to store the last time we double click & the time between clicks.
  • Declare tripleClickEventFired to indicate we have already fired an event (init to false)

Handlers

Click Handler

if ((clock() - doubleClickFiredTime) < doubleClickInterval)
    <fire triple click event>
    tripleClickFired = true;
else
    <fire click event>

Double click handler

doubleClickTime == clock()
doubleClickInterval == GetDoubleClickTime() * CLOCKS_PER_SEC / 1000;

If ( !tripleClickEventFired)
    <fire doubleClickEvent>
else
    tripleClickEventFired = false;

The functions I use was:

  • clock(): get the current system time in UNIT
  • GetDoubleClickTime(): a function provided by Windows to get the time between clicks
  • the "* CLOCKS_PER_SEC / 1000;" part is meant to covert the return value of GetDoubleClickTime() to UNIT'''

NOTE: the 3rd click fires both a Click and Double Click event on system level

Perspicacious answered 21/12, 2011 at 22:19 Comment(0)
A
1

I have adapted Jimmy T's answer to encapsulate the code into a class and to make it easier to apply to multiple controls on a form.

The class is this:

    using System.Windows.Forms;

    public class TripleClickHandler
    {
        private int _clicks = 0;
        private readonly System.Windows.Forms.Timer _timer = new System.Windows.Forms.Timer();
        private readonly TextBox _textBox;
        private readonly ToolStripTextBox _toolStripTextBox;

        public TripleClickHandler(TextBox control)
        {
            _textBox = control;
            _textBox.MouseUp += TextBox_MouseUp;
        }
        public TripleClickHandler(ToolStripTextBox control)
        {
            _toolStripTextBox = control;
            _toolStripTextBox.MouseUp += TextBox_MouseUp;
        }
        private void TextBox_MouseUp(object sender, MouseEventArgs e)
        {
            _timer.Stop();
            _clicks++;
            if (_clicks == 3)
            {
                // this means the trip click happened - do something
                if(_textBox!=null)
                    _textBox.SelectAll();
                else if (_toolStripTextBox != null)
                    _toolStripTextBox.SelectAll();
                _clicks = 0;
            }
            if (_clicks < 3)
            {
                _timer.Interval = 500;
                _timer.Start();
                _timer.Tick += (s, t) =>
                {
                    _timer.Stop();
                    _clicks = 0;
                };
            }
        }
    }

Then, to apply it to a textbox you can do this:

partial class MyForm : Form
{
    UIHelper.TripleClickHandler handler;
    public MyForm()
    {
        InitializeComponent();
        handler = new UIHelper.TripleClickHandler(myTextBox);
    }
}

Or, if you aren't otherwise using the control's tag you can simply do this:

partial class MyForm : Form
{
    public MyForm()
    {
        InitializeComponent();
        myTextBox.Tag = new UIHelper.TripleClickHandler(myTextBox);
    }
}
Auliffe answered 22/5, 2020 at 16:40 Comment(1)
Brilliant! Glad you were able to use thisGobetween
D
0

I expanded on Jimmy T's answer, and introduced logic so that 3 clicks will select a single line/paragraph (between nearest 2 carriage returns), while 4 clicks will select the entire text:

private void txtTextMessage_MouseUp(object sender, MouseEventArgs e)
{
    _timer.Stop();
    _clicks++;
    if (_clicks == 4)
    {
        //Select the whole text
        txtTextMessage.SelectAll();
        _clicks = 0;
    }
    if (_clicks == 3)
    {
        //Select the current "paragraph"
        var currentCursorPosition = txtTextMessage.SelectionStart;
        var beginningOfParagraph = txtTextMessage.Text.LastIndexOf("\n", currentCursorPosition) + 1; //if not found, will be 0, which is start of string
        var endOfParagraph = txtTextMessage.Text.IndexOf("\r\n", currentCursorPosition); //first look for next CRLF
        if (endOfParagraph < 0)
        {
            endOfParagraph = txtTextMessage.Text.IndexOf("\n", currentCursorPosition); //if not found, look for next LF alone
            if (endOfParagraph < 0)
                endOfParagraph = txtTextMessage.Text.Length; //if still not found, use end of string
        }
        txtTextMessage.SelectionStart = beginningOfParagraph;
        txtTextMessage.SelectionLength = endOfParagraph - beginningOfParagraph;
    }
    if (_clicks < 4)
    {
        _timer.Interval = 500;
        _timer.Start();
        _timer.Tick += (s, t) =>
        {
            _timer.Stop();
            _clicks = 0;
        };
    }
}
Discretion answered 12/5, 2023 at 18:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.