views:

1840

answers:

5

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.

+7  A: 

This should do the trick:

    private void maskedTextBox1_Enter(object sender, EventArgs e)
    {
        this.BeginInvoke((MethodInvoker)delegate()
        {
            maskedTextBox1.Select(0, 0);
        });         
    }
Abbas
Ahh, so you need to use BeginInvoke! I tried this without doing so and ended up not seeing any change. +1
Jeremy
Why do you need to use BeginInvoke?
Vaccano
A: 

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...

mdb
+2  A: 

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.

Ishmaeel
Thanks for the little tweak. Just what I needed.
Noam Gal
You can cater that with same code with using it for both Enter and Click functions for the Maskedtextbox :)
Mobin
A: 

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 ); });
}
Mike M
A: 

How do you do this.BeginInvoke() in VB?

Try Me.BeginInvoke
benPearce