Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When Clicking a Textbox, How to Give it Focus but Not Change the Cursor Location Inside It [closed]

Tags:

c#

.net

winforms

I created an event handler for the Textbox.Enter event, which selects a part of the text inside the textbox, like this:
TextBox1.Select(3,5);

The result looks like this:

When the Textbox is entered via the Keyboard via [Tab] or [Shift]-[Tab],
the part of the text that needs to be selected is selected well, just like in the screenshot above.

However if the textbox is entered not via the keyboard but via the mouse,
then nothing is selected:

It seems that what happens is this:

When we enter the textbox with the mouse,
the click indeed raises the Enter event, but the mouseclick also sets the location of the cursor, to the location the user clicked with the mouse, inside the textbox.
And this setting of the cursor happens right after the event handler was ran.

So this means, that the selection that the event handler performed (with the TextBox1.Select(3,5); line), is overridden by the mouse's location,
and that's why entering the textbox with the mouse, appears to not select anything.

My question:

How can I make the mouse indeed raise the Enter event, yet not change the cursor position inside the textbox?
So I will then be able to have my selection (that happens in code) remain and not be overridden..

Edit:
The purpose of this is to enable easy selection of the MM:SS part of the time, which is usually the part that is being edited (the HH or mmm parts are rarely changed).

like image 634
spaceman Avatar asked Oct 18 '22 18:10

spaceman


2 Answers

A bit strange request, but if you really want to do so, you can use a well known general method for scheduling an action to be executed later (after normal windows message/event processing) by using the Control.BeginInvoke method.

Something like this

void textBox_Enter(object sender, EventArgs e)
{
    BeginInvoke(new Action(() => textBox.Select(3, 5)));
}

Update: As per your comment, if you want to prevent the default mouse down behavior, you need to handle the WM_MOUSEACTIVATE message by creating and using your own TextBox subclass like this

class MyTextBox : TextBox
{
    protected override void WndProc(ref Message m)
    {
        const int WM_LBUTTONDOWN = 0x0201;
        const int WM_MOUSEACTIVATE = 0x0021;
        const int MA_ACTIVATEANDEAT = 2;
        const int MA_NOACTIVATEANDEAT = 4;

        if (m.Msg == WM_MOUSEACTIVATE && !Focused)
        {
            int mouseMsg = unchecked((int)((uint)(int)m.LParam >> 16)); // LOWORD(m.LParam)
            if (mouseMsg == WM_LBUTTONDOWN)
            {
                bool activated = Focus();
                m.Result = (IntPtr)(activated ? MA_ACTIVATEANDEAT : MA_NOACTIVATEANDEAT);
                return;
            }
        }
        base.WndProc(ref m);
    }
}
like image 190
Ivan Stoev Avatar answered Oct 21 '22 15:10

Ivan Stoev


I would like to suggest another way:

In the beginning of the Control.Enter event handler, I put this:

while( (Control.MouseButtons&MouseButtons.Left)!=0 )
    Application.DoEvents();

This simply waits for the mouse Left button to be released..

Only when the mouse Left button is released, then we continue to the next line of code, which is

TextBox1.Select(3,5);

and it then works well - the selection happens, without being overridden.

like image 38
spaceman Avatar answered Oct 21 '22 17:10

spaceman