The MaskedTextBox Control

The MaskedTextBox control provides restricted data input as well as formatted data output. This control supplies visual cues about the type of data being entered or displayed. It can be useful in data entry applications in that it can prevent the user from entering invalid data.

In my opinion, the masked textbox control is suitable for the entry of some types of data items, but inadequate for others.

The masked textbox control is GOOD for items that are fixed in length with a defined format, such as Social Security Numbers, phone numbers, zip codes; generally anything with a fixed number of digits and/or letters (account numbers, state abbreviations, etc.).

It is "so-so" for dates (you must enter all digits and it does not validate the correctness of the date).

The masked textbox control is BAD for numeric items with a decimal point where the number of digits before and/or after the decimal point can vary (such money amounts, rates, measurements, etc.). This is because the control will not right-align the value nor line up the decimal point as you enter the value. For these types of numeric values, you are better off using the standard TextBox control and monitoring the user's input "manually" with the KeyPress event.

The MaskedTextbox control can be found in the "Common Controls" section of the Toolbox:

 

 

The Mask Property

 

The Mask property is the "heart" of the MaskedTextBox control. With it, you define the pattern of the data item to be entered into the control. The following masking elements (characters) can be used to set the Mask property:

Masking Element

Description

0

Digit, required. Only the digits 0 through 9 can be entered in this position.

9

Digit or space, optional.

#

Digit or space, optional. Plus (+) and minus (-) signs are allowed.

L

Letter, required. Restricts input to the ASCII letters a-z and A-Z.

?

Letter, optional. Restricts input to the ASCII letters a-z and A-Z.

&

Character, required. If the AsciiOnly property is set to true, this mask element behaves like the "L" element.

C

Character, optional. Any non-control character. If the AsciiOnly property is set to true, this mask element behaves like the "?" element.

A

Alphanumeric, required. If the AsciiOnly property is set to true, the only characters it will accept are the ASCII letters a-z and A-Z. This mask element behaves like the "a" element.

a

Alphanumeric, optional. If the AsciiOnly property is set to true, the only characters it will accept are the ASCII letters a-z and A-Z. This mask element behaves like the "A" element.

.

Decimal placeholder. The actual display character depends on the computer's International Settings.

,

Thousands placeholder. The actual display character depends on the computer's International Settings.

:

Time separator. The actual display character depends on the computer's International Settings.

/

Date separator. The actual display character depends on the computer's International Settings.

$

Currency symbol. The actual display character depends on the computer's International Settings.

Shift down. Converts all characters that follow to lowercase.

Shift up. Converts all characters that follow to uppercase.

|

Disable a previous shift up or shift down.

\

Escape. Escapes a mask character, turning it into a literal. "\\" is the escape sequence for a backslash.

All other characters

Literals. All non-mask elements will appear as themselves. Literals always occupy a static position in the mask at run time, and cannot be moved or deleted by the user.

 

The TextMaskFormat Property

 

The TextMaskFormat property specifies whether or not prompt characters and/or other literal characters are included in the Text property (the default prompt character is the underscore). The possible values for the TextMaskFormat property are:

            ExcludePromptAndLiterals

            IncludePrompt

            IncludeLiterals

            IncludePromptAndLiterals

For example, if MaskedTextBox1 specified a Mask of "###-##-####" and the user entered "123121234", the control would display "123-12-1234". If TextMaskFormat property is set to IncludePromptAndLiterals, then the value of MaskedTextBox1.Text would be 123-12-1234, and Len(MaskedTextBox.Text) would be 11.  If TextMaskFormat is set to ExcludePromptAndLiterals, then the value of MaskedEdBox1.Text would be 123121234, and Len(MaskedEdBox.Text) would be 9. In most cases, it is appropriate to set the TextMaskFormat property to ExcludePromptAndLiterals  – otherwise, extra logic may be needed to parse out the actual value that the user entered.

 

 

MaskedTextBox Control Demo Program

 

The demo program presents the user with a form containing various input fields (MaskedTextBox boxes), as shown below:

 

 

When the user fills in the fields and clicks the Process button, the application validates the entries and reports the results in the multi-line textbox at the bottom of the screen:

 

 

Clicking the Pre-Fill button populates the MaskedTextBox boxes with predetermined values (this demonstrates how to populate MaskedTextBox controls through code):

 

 

The Clear button clears the contents of the MaskedTextBox controls; the Exit button ends the program.

 

 

The form at design-time is shown below:

 

To build the sample application, arrange the controls on the form as shown. Set the properties of the six MaskedTextBox controls as follows:

 

Name

Mask

TextMaskFormat

mskSSN

###-##-####

ExcludePromptAndLiterals 

mskPhone

(###) ###-####

ExcludePromptAndLiterals 

mskDate

##/##/####

IncludeLiterals

mskState

>??

ExcludePromptAndLiterals 

mskUSZip

####-####

ExcludePromptAndLiterals 

mskCanZip

>?#? #?#

ExcludePromptAndLiterals 

 

Set the properties of the four buttons as follows:

 

Name

Text

btnProcess

Process

btnPreFill

Pre-Fill

btnClear

Clear

btnExit

Exit

 

Set the properties of the multi-line textbox as follows:

 

Property

Value

Name

txtResults

MultiLine

True

Scrollbars

Vertical

ReadOnly

True

 

Code the General Declarations section as follows (there is one form-level variable, an array named mastrUSStates, which will store the 50 valid US state abbreviations):

 

Private mastrUSStates() As String = {"AK", "AL", "AR", "AZ", "CA", "CO", "CT", "DC", "DE", "FL", _

                                     "GA", "HI", "IA", "ID", "IL", "IN", "KS", "KY", "LA", "MA", _

                                     "MD", "ME", "MI", "MN", "MO", "MS", "MT", "NC", "ND", "NE", _

                                     "NH", "NJ", "NM", "NV", "NY", "OH", "OK", "OR", "PA", "RI", _

                                     "SC", "SD", "TN", "TX", "UT", "VA", "VT", "WA", "WI", "WV", "WY"}

 

Code the btnProcess_Click event as follows. Note that the tests for the lengths of the Text property of all the MaskedTextBox controls except for the mskDate control test for the length of the item excluding the mask characters - because the TextMaskFormat property for those was set to ExcludePromptAndLiterals. The length test for mskDate is 10 rather than 8 because the TextMaskFormat property for that control is set to IncludeLiterals.

 

    Private Sub btnProcess_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles btnProcess.Click

 

        If Len(mskSSN.Text) = 9 Then

            DisplayMessage("SSN is OK.")

        Else

            DisplayMessage("SSN is missing or incomplete.")

        End If

 

        If Len(mskPhone.Text) = 10 Then

            DisplayMessage("Telephone Number is OK.")

        Else

            DisplayMessage("Telephone Number is missing or incomplete.")

        End If

 

        If Len(mskDate.Text) = 10 Then

            If IsDate(mskDate.Text) Then

                DisplayMessage("Date is OK.")

            Else

                DisplayMessage("Date is invalid.")

            End If

        Else

            DisplayMessage("Full date in MM/DD/YYYY format is required.")

        End If

 

        If ValidState() Then

            DisplayMessage("U.S. State is OK.")

        Else

            DisplayMessage("U.S. State is invalid.")

        End If

 

        If Len(mskUSZip.Text) = 5 Or Len(mskUSZip.Text) = 9 Then

            DisplayMessage("U.S. Zip is OK.")

        Else

            DisplayMessage("U.S. Zip is missing or incomplete.")

        End If

 

        If Len(mskCanZip.Text) = 6 Then

            DisplayMessage("Canadian Zip is OK.")

        Else

            DisplayMessage("Canadian Zip is missing or incomplete.")

        End If

 

    End Sub

 

 

Code the btnPreFill_Click event as follows. Once again, the TextMaskFormat issue comes into play. Note that we are assigning "raw" data to each of the MaskedTextBox controls except for mskDate, where the slashes are included. When TextMaskFormat is set to IncludeLiterals, the data assigned to the control must match the mask - otherwise, an error will occur.

 

    Private Sub btnPreFill_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles btnPreFill.Click

 

        mskSSN.Text = "123121234"

        mskPhone.Text = "1112223333"

        mskDate.Text = FormatDateTime(Date.Today, DateFormat.ShortDate)

        mskState.Text = "WV"

        mskUSZip.Text = "123451234"

        mskCanZip.Text = "R3C0V8"

 

        txtResults.Text = ""

 

    End Sub

 

Code the btnClear_Click event as follows. Here, the contents of the MaskedTextBox controls are cleared by assigning the zero-length string ("") to each control. However, for the mskDate control, where the TextMaskFormat property is set to IncludeLiterals, a special technique is required. We must first clear the Mask property, then clear the Text property. After that is done, we can reset the Mask property.

 

    Private Sub btnClear_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles btnClear.Click

 

        mskSSN.Text = ""

        mskPhone.Text = ""

 

        mskDate.Mask = ""

        mskDate.Text = ""

        mskDate.Mask = "##/##/####"

 

        mskState.Text = ""

        mskUSZip.Text = ""

        mskCanZip.Text = ""

 

        txtResults.Text = ""

 

        mskSSN.Focus()

 

    End Sub

 

Code the btnExit_Click event as follows to end the program.

 

    Private Sub btnExit_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles btnExit.Click

        Me.Close()

    End Sub

 

Code the DisplayMessage Sub as follows. This Sub is used to build the information that appears in the multi-line textbox on the lower half of the form.

 

    Private Sub DisplayMessage(ByRef pstrMsg As String)

        txtResults.Text = txtResults.Text & vbNewLine & pstrMsg

    End Sub

 

Code the ValidState function. This function checks the user's entry in the mskState control against the array of valid US states to determine if a valid state was entered.

 

    Private Function ValidState() As Boolean

 

        Dim intX As Integer

 

        For intX = 0 To UBound(mastrUSStates)

            If mskState.Text = mastrUSStates(intX) Then

                Return True

                Exit For

            End If

        Next

 

        Return False

 

    End Function

 

End Class

 

 

Download the project files for this sample application here.