This has been driving me nuts for ages. If the focus of a VB.NET app is a MaskedTextBox, anytime a MessageBox is displayed, the cursor location of the MaskedTextBox resets to the 2nd letter. Why? Any ideas how to prevent this?
Here's how to replicate:
Create a blank Winforms app, add a MaskedTextBox. Set the Mask to ">&&&&&&-&". Add the following code to the form:
Public Class Form1
Private Sub MaskedTextBox1_TextChanged(sender As Object, e As EventArgs) Handles MaskedTextBox1.TextChanged
If MaskedTextBox1.Text = "000000-" Then
MsgBox("hi")
End If
End Sub
End Class
Run the app. Start typing 0's into the text box. Notice that when you hit the 6th zero and the MsgBox is fired, the cursor moves back to the 2nd letter.
EDIT: This has nothing to do with the message box itself. It seems to have something to do with any other form showing. See this example:
Public Class Form1
Private Sub MaskedTextBox1_TextChanged(sender As Object, e As EventArgs) Handles MaskedTextBox1.TextChanged
If MaskedTextBox1.Text = "000000-" Then
Dim f As New Form1
f.Show() 'after you close the new form, the cursor will have moved in the first!
End If
End Sub
End Class
The
MaskedTextBoxoverrides OnTextChanged, to set some state that allows to determine later what is the actual length of the text and the mask, or a mix of the two, depending on what the Control needs to present to the user.To keep it simple (or read what's at the bottom), you should allow the sequence of method calls generated by the event to complete, before you do something that moves the Focus somewhere else, generating a new sequence of method calls and validation events that end up compromising the registration of states in some Controls.
This applies to different events of other Controls as well.
To defer the presentation of the MessageBox, you can BeginInvoke() it.
The code that follows is executed asynchronously, after the
TextChangedevent has completed its procedures:If you need to handle the result of the MessageBox, do that in the same way:
You can also set a Field to the result of the Dialog and inspect it somewhere else.
The same if you show a Form instead, Modal or not:
If you're interested in what happens under the hood, see the code that sets the final state in the
OnTextChangedoverride, and read the notes here, then see what happens when the OnTextChanged method of the base class is called.You can infer what happens after, when SetWindowText() is called for other reasons (
OnTextChange()is also called when the mask is set back to the Control, when it's been computed what part is the text and what part is the mask)