Question

I would like to be able to override the default behaviour for positioning the caret in a masked textbox.

The default is to place the caret where the mouse was clicked, the masked textbox already contains characters due to the mask.

I know that you can hide the caret as mentioned in this post, is there something similar for positioning the caret at the beginning of the textbox when the control gets focus.

Was it helpful?

Solution

This should do the trick:

    private void maskedTextBox1_Enter(object sender, EventArgs e)
    {
        this.BeginInvoke((MethodInvoker)delegate()
        {
            maskedTextBox1.Select(0, 0);
        });         
    }

OTHER TIPS

To improve upon Abbas's working solution, try this:

private void ueTxtAny_Enter(object sender, EventArgs e)
{
    //This method will prevent the cursor from being positioned in the middle 
    //of a textbox when the user clicks in it.
    MaskedTextBox textBox = sender as MaskedTextBox;

    if (textBox != null)
    {
        this.BeginInvoke((MethodInvoker)delegate()
        {
            int pos = textBox.SelectionStart;

            if (pos > textBox.Text.Length)
                pos = textBox.Text.Length;

            textBox.Select(pos, 0);
        });
    }
}

This event handler can be re-used with multiple boxes, and it doesn't take away the user's ability to position the cursor in the middle of entered data (i.e does not force the cursor into zeroeth position when the box is not empty).

I find this to be more closely mimicking a standard text box. Only glitch remaining (that I can see) is that after 'Enter' event, the user is still able to select the rest of the (empty) mask prompt if xe holds down the mouse and drags to the end.

That is a big improvement over the default behaviour of MaskedTextBoxes. Thanks!

I made a few changes to Ishmaeel's excellent solution. I prefer to call BeginInvoke only if the cursor needs to be moved. I also call the method from various event handlers, so the input parameter is the active MaskedTextBox.

private void    maskedTextBoxGPS_Click( object sender, EventArgs e )
{
    PositionCursorInMaskedTextBox( maskedTextBoxGPS );
}


private void    PositionCursorInMaskedTextBox( MaskedTextBox mtb )
{
  if (mtb == null)    return;

  int pos = mtb.SelectionStart;

  if (pos > mtb.Text.Length)
    this.BeginInvoke( (MethodInvoker)delegate()  { mtb.Select( mtb.Text.Length, 0 ); });
}

Partial answer: you can position the caret by assigning a 0-length selection to the control in the MouseClick event, e.g.:

MaskedTextBox1.Select(5, 0)

...will set the caret at the 5th character position in the textbox.

The reason this answer is only partial, is because I can't think of a generally reliable way to determine the position where the caret should be positioned on a click. This may be possible for some masks, but in some common cases (e.g. the US phone number mask), I can't really think of an easy way to separate the mask and prompt characters from actual user input...

//not the prettiest, but it gets to the first non-masked area when a user mounse-clicks into the control
private void txtAccount_MouseUp(object sender, MouseEventArgs e)
{
  if (txtAccount.SelectionStart > txtAccount.Text.Length)
    txtAccount.Select(txtAccount.Text.Length, 0);
}

This solution works for me. Give it a try please.

private void maskedTextBox1_Click(object sender, EventArgs e)
{

 maskedTextBox1.Select(maskedTextBox1.Text.Length, 0);
}

I got mine to work using the Click event....no Invoke was needed.

 private void maskedTextBox1_Click(object sender, EventArgs e)
{
     maskedTextBox1.Select(0, 0);              
}

This solution uses the Click method of the MaskedTextBox like Gman Cornflake used; however, I found it necessary to allow the user to click inside the MaskedTextBox once it contained data and the cursor stay where it is.

The example below turns off prompts and literals and evaluates the length of the data in the MaskedTextBox and if equal to 0 it puts the cursor at the starting position; otherwise it just bypasses the code that puts the cursor at the starting position.

The code is written in VB.NET 2017. Hope this helps!

Private Sub MaskedTextBox1_Click(sender As Object, e As EventArgs) Handles MaskedTextBox1.Click
    Me.MaskedTextBox1.TextMaskFormat = MaskFormat.ExcludePromptAndLiterals
    If Me.MaskedTextBox1.Text.Length = 0 Then
        MaskedTextBox1.Select(0, 0)
    End If
    Me.MaskedTextBox1.TextMaskFormat = MaskFormat.IncludePromptAndLiterals
End Sub
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top