Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

A Simple Number Entry Textbox

0.00/5 (No votes)
2 Dec 2009 1  
A simple entry box for various numbers, especially phone numbers.

Introduction

Here's a modified MaskedTextBox that makes it easy to type various numbers, since the numbers "push in" from the right as you type them, the way it does on a pocket calculator.

Background

Here's why I've made this control:

When tabbing into a phone number field or clicking in, I've noticed it's easy to "miss", and you have to do more clicking or arrow-ing to get to the spot where the number looks right when entered.

For example, if you place a MaskedTextBox on your form for telephone number entry, it would usually include the area code digit positions. But what if the user doesn't need to enter an area code?

(___) 555-1212

Problem is, when the user tabs in, the cursor by default would appear at the beginning of the area code portion. Or if the user clicks in, it's easy to click into the control at the wrong spot as well.

But there is an easier way. The way you enter text on your pocket calculator is better. The numbers always "push in" from the right side of the display.

So I decided to make a phone number entry box, which (during entry via the keyboard) only accepts digits and the backspace (or left-arrow does the same). If the number has 7 digits, it will look like the above. If you keep typing, you get all ten digits.

(Oh, you can set the value (the phone number value that is) using the A_Text property. Anyone wants to add the capability to paste a number in? )

By the way, if you click somewhere in the box when a number is already there, it deletes the characters to the right of the click position, for convenience.

Using the Code

Unzip the download and add the two items to your project folder, then open your project and right-click on the project, then "Add..", and finally locate and open CoolNumberBox.vb.

The existing code provides ten different masks for various numbers, including 7-digit, 10-digit, and 11-digit entry for (North American) long distance numbers that need a "1" on the front of the number.

Public Enum NumberMasks
   One_Digit_X
   Two_Digit_XX
   Three_Digit_XXX
   Four_Digit_XXXX
   Five_Digit_XXXXX
   Seven_Digit_555_1212
   Ten_Digit_800_555_1212
   Eleven_Digit_1_800_555_1212
   Area_Code_Plus_Exchange_XXX_XXX
   Time_as_Hours_and_Minutes_X_XX
End Enum

Also, if you wanted to add support for international telephone number entry, you would need to change the masks. If you do, please make sure you adjust the mMaxLen and mEmptyMask variables to agree with your mask, in the Set block of the A_PhoneNumberMask property.

The field mMaxLen represents the length of the "raw" number, so for example: (800) 555-1212 has a length of 10.

Accordingly, the mEmptyMask field has mMaxLen number of spaces.

Finally, the Mask property of MaskedTextBox is set (internally) according to standard masking principles, which you can get by looking up the MaskedTextBox and its properties.

By the way, you'll notice that I have prepended "A_" to my custom property names. This is to cause intellisense to put them at the top of the list. Why? Because, months later, I always forget what my custom property names were, but with this method, they're always right there, and grouped together as a bonus.

The code is annotated, so download the code and give it a try.

Points of Interest

burlyeman24 has found a better way of dealing with the problem of backspacing, which is discussed a bit further down. Before I discuss the problem (which is now fixed!), I'll show the new solution. The key is to call the TheTextChanged sub *before* setting e.Handled=True.

The older, inferior way of handling the problem was attempting to overcome the problem in the OnKeyUp handler:

Protected Overrides Sub OnKeyUp(ByVal e As System.Windows.Forms.KeyEventArgs)
   If Me.ReadOnly Then Exit Sub
   'this serves to refresh the text when the backspace key is let up
   If e.KeyCode = Keys.Back Then TheTextChanged(mTheText)
   MyBase.OnKeyUp(e)
End Sub 

The corrected, better way, located in the OnKeyDown hander, is first calling TheTextChanged, *then* setting e.Handled=True:

Case Keys.Left, Keys.Back
   'remove the last character from our text
   If Len(mTheText) Then mTheText = Mid(mTheText, 1, Len(mTheText) - 1)
   'thanks to burleyman24
   TheTextChanged(mTheText
   e.Handled = True
   Exit Sub 

I used the SelectionStart property of the MaskedTextBox control to force the cursor to sit at the end of the text of the MaskedTextBox. This is basic to my philosophy here, of "pushing in" the characters from the right side, like in a cash register.

Private Sub TheTextChanged(ByVal ControlText As String)
    'left-fill the text of the MaskedTextBox with spaces. 
    'this has the effect of right-justifying the text 

    Text = Mid(mEmptyMask, 1, mMaxLen - Len(ControlText)) + ControlText

    'put the cursor at the end 
    SelectionStart = Mask.Length
End Sub 

I want you to feel free to use and change this code in your own project. If you wish to acknowledge my work within your project, such as in a Thanks To: box, that would be nice. As well, you should respect my Copyright statement at the top of the code, by leaving it there to remind you where it came from.

History

  • July 13, 2007 - First version.
  • July 14, 2007 - Converted the project to a component instead of a UserControl.
  • November 17, 2008 - Implemented a superior way of backspacing, thanks to burleyman24.
  • Dec 2, 2009 - Editing changes for clarity. Updated zip to the latest version I have.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here