# VBForums CodeBank > CodeBank - Visual Basic 6 and earlier >  VB - An ActiveX control which restricts a textbox to numbers

## MartinLiss

The attached control is a modified TextBox which restricts the user to numbers. The control also has these additional properties:

*CanHaveDecimals* - A Boolean property that determines if the number can have decimals

*CanBeNegative* - A Boolean property that determines if the number can be negative

*MaxDecimals* - Allows the maximum number of decimals to be set

*MinValue* - Allows the minimum value to be set

*MaxValue* - Allows the maximum value to be set

*DecimalSeparator* - Determines which character ("." or ",") is used as the decimal separator

*RequireLeadingDigit*   *(New)* - Determines if at least one digit must preceed the decimal separator. 

The code for the control is included in the zip file.

NOTES: 
Version 1.1: Updated to include most of the normal properties associated with a textbox. Also includes the bug fix provided by dee-u.Version 1.2: Add Click eventVersion 1.3: Add SelStart, SelLen and SelText propertiesVersion 1.4: Corrected implementation of SelStart, SelLen and SelText and also added several other propertiesVersion 1.5: Changed the names of the NumberBoxClick and NumberBoxKeyPress events to Click and KeyPress. Added KeyUp, KeyDown and Change events, and corrected DblClick eventVersion 1.6: 12/02/2006 Corrected KeyUp, KeyDown, and KeyPress properties by adding standard parametersVersion 1.7: 02/07/2007 Added Enums for Alignment and BorderStyle properties.  Corrected problem where numberbox behaved as if it was locked when data with decimal points was added, and added protection against pasting in invalid characters (which I thought it already had)Version 1.8: 02/07/2007 Added support for paste via ctrl-V and allow for an almost unlimited number of decimalsVersion 1.9: 06/11/2007 Added MinValue and MaxValue propertiesVersion 1.10: 02/27/2008 Added DecimalSeparator property. Also fixed a bug which occurred when more than the allowed number of decimals was enteredVersion 1.11: 03/14/2008 Changed code so that an attempt to add a second decimal separator is ignored rather than causing the first one to be removed. Corrected bug where adding a decimal separator to a negative number would cause one too few decimal places to be shown.Version 1.12: 04/25/2008 Corrected MaxValue and MinValue processing when comma is the decimal separator. Changed the Appearance  property values so that they display Flat and 3D like the normal textbox rather than 0 and 1Version 1.13: 05/02/2008 
Corrected MinValue and MaxValue processing so that the entry of a minus sign doesn't result in a type mismatch error.Changed MinValue and MaxValue processing so that if a change would violate either limit, the old value is restored rather than changing it to the MinValue or MaxValue.Corrected spelling of DecimalSeparator property.Added a Test project for those who might want to debug my code.Version 1.14: 10/20/2008 
Made .text the default property.Added categories to propertiesVersion 1.15: 03/29/2009 Corrected problem where previously if you had a number that contained a decimal separator, and you selected the number with the intention of entering a new number that started with a decimal separator, the entry of the decimal separator was not allowed because it was assumed you were trying to add a second decimal separator.Version 1.16: 04/03/2009
Added RequireLeadingDigit property. For example .15 would be changed to 0.15 if set to True.Removed MaxLength and PasswordChar propertiesChanged behavior where if number was greater than the MaxValue or less than the MinValue it dropped the last digit. New behavior changes the value to MaxValue or MinValue as appropriate.

KNOWN PROBLEMS: None

----------


## dee-u

I fixed a small flaw in the above project, here is the updated version...

[Edited by MartinLiss]dee-u's code is now out of date.

----------


## litlewiki

Heyy i found something interesting .Maybe this can reduce the size of the code in some way

VB Code:
//module
Public Const GWL_STYLE = (-16)
 ' Restricts input to the edit control to digits only
Public Const ES_NUMBER = &H2000
 Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
                              (ByVal hwnd As Long, ByVal nIndex As Long, _
                              ByVal dwNewLong As Long) As Long
  Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" _
                            (ByVal hwnd As Long, ByVal nIndex As Long) As Long
//end module
form code

VB Code:
Private Sub Form_Load()
  SetWindowLong Text1.hwnd, GWL_STYLE, _
                          GetWindowLong(Text1.hwnd, GWL_STYLE) Or _
                          ES_NUMBER
 End Sub

----------


## MartinLiss

I updated the zip file above with code that includes a Click event. If you need any other events you can look for the two changes that I made (marked by "' new") for the Click event.

----------


## MartinLiss

Zip file updated.

----------


## MartinLiss

Zip file updated again - sorry.

----------


## MartinLiss

Updated to Version 1.6.

----------


## mkkmkk

i need the last version of the numberbox for excel 2003, and the instructions how to install it.

thanks

----------


## MartinLiss

> i need the last version of the numberbox for excel 2003, and the instructions how to install it.
> 
> thanks


Sorry but my ocx has nothing to do with excel.

----------


## mkkmkk

themks

----------


## mkkmkk

thanks, why doesn´t work in a form of excel?

----------


## MartinLiss

Updated to Version 1.7.

----------


## rjbudz

I tried out V 1.7 in my 'Numbers To English' program (in  [RESOLVED] VB6/ Number to Words / 66 digits) .  It works very well (good job!) except the limit on digits to the right of the decimal point.  In theory, the number of digits (to the right) could be the maximum the textbox will take (in theory!).  I'm sure it won't often happen.  

But sometimes, in 'normal' apps, the number of decimal digits will not be know at design time.

Is there a reason you are limiting decimals to a defined design-time value? If so, would I need to add one more allowable decimal digit each time the user adds one to the control?  Is there a point at which it'll blow up? 

Either way, it seems like a lot of overhead.

Also, the paste-into fuctionality isn't working   :Frown:

----------


## MartinLiss

I'm not limiting the decimals. I believe you over looked the MaxDecimals property. I'll look into the paste problem, thanks.

----------


## rjbudz

Setting the MaxDecimals property is, well, setting the maximum number of decimals.  The object is to NOT set a maximum number of decimals and allowing the user to enter them to his/her heart's content! 

Did I miss something?  :Confused:

----------


## sgrya1

I like the decimal restriction. My nbrboxes are too small to have the user going overboard on decimal places. I've also an whole upper number limit so that the number is never greater than the nbrbox size.
It is a user input box and I doubt that anyone will spend time adding or pasting in more than 9,999 decimal places. A numberbox that is 10,000 characters would also need to be pretty big.
If you are writing to the nbrbox round the number to 9,999th decimal place or there abouts.

----------


## rjbudz

You're probably right. I doubt it will ever be a problem  

The textbox maxes out at 65,535 (me thinks, though some sources say 32,000) characters. 10,000 isn't bad.  I suppose, all things considered, that's a fair limit.

I'm really amazed this hadn't been done defore.  Is seems so obvious in hind-sight.  I'm certain it'll be used far & wide.

Nicely done.  


Just-a-waiting on that paste thing (   :Big Grin:   ) ...

----------


## rjbudz

About the max limit of chars to a textbox:  Here is the word from the Power-That-Is (Microsoft):

"The Text setting for a TextBox control is limited to 2048 characters unless the MultiLine property is True, in which case the limit is about 32K." *


_About_?  What's THAT mean?   :Confused:  

* http://msdn.microsoft.com/library/de.../vbprotext.asp

----------


## MartinLiss

> Setting the MaxDecimals property is, well, setting the maximum number of decimals.  The object is to NOT set a maximum number of decimals and allowing the user to enter them to his/her heart's content! 
> 
> Did I miss something?


Okay I think I misunderstood you. I felt I was not limiting it because you can use the MaxDecimals in the IDE or in code to increase the maximum, but now I see that you don't want even that "restriction".  I will try to change it so that it can be unlimited by default.

----------


## rjbudz

The tricky part will be how to set MaxDecimals to infinity.  Setting to zero means no decimals.

----------


## MartinLiss

I will try blank to indicate no limit.

----------


## rjbudz

Yeah, that's how Index is done.  In leu of that (in case you're using Integer or Long) you could do the TabStop (True/False) and TabIndex (numeric).

----------


## MartinLiss

> ...In leu of that (in case you're using Integer or Long) you could do the TabStop (True/False) and TabIndex (numeric).


I'm not sure what you mean by that. Is there something wrong with those two properties of my control?

----------


## rjbudz

:Smilie:   No, don't worry.  I was just suggesting how you might implement the infinite decimal allowance part of your control.

Just trying to be of assistance.  There's nothing wrong.

----------


## MartinLiss

Right now I have it working in my copy this way. If you blank out the MaxDecimals it changes it to 9999. Is that acceptable?

----------


## rjbudz

Sure, but I could set MaxDecimal to 9999 anyway, hence the added code to automatically set it to 9999 isn't really neccessary. 

So, the short answer is: If infinity is out of the question, just leave is the way it is in the last release.  As you've written it, any value entered in excess of 9999 automatically sets the vale to it (9999), as would be expected.

My intent isn't to get you to re-write it for my benefit.  I like it just fine (except for the paste-thing  :Smilie:  )  I just suggested ASSUMED infinity for decimals.

----------


## MartinLiss

Updated to Version 1.8.

----------


## rjbudz

Nice.  Does it fix the paste problem?  :Big Grin:  

And, oh BTW, I couldn't let the textbox limit ambiguity rest ('tis my nature), so I tested it with a single line and multi-line textbox.  It took overnight to run, the multi-line textbox seemed to take longer and longer to calculate _textbox2 = textbox2 & "X"._ Textbox1 (single line) didn't seem to take longer.  (No I'm not going to run timers!)

Anyway, both textboxes max out at 65,535.  This is in direct contrast to what Microsoft stated.  Also, there is no error message when the max is reached.  Instead it just doesn't add anymore chars (as opposed to dropping off the first ones to accommodate the last). 

I know everyone is going to sleep better knowing this!  :Smilie:

----------


## MartinLiss

> Nice.  Does it fix the paste problem? ....


If you mean can you now paste via ctrl-v then yes. If you mean something else then please let me know.

----------


## rjbudz

Nope.  That is what I meant.  I rate Excellent!  Thank you!

----------


## rjbudz

Hi again.

I noticed that if a user enters a second decimal point, the first decimal point disappears.  

The user will probably not notice this event (I didn't) and will continue to happily enter numbers, and then click the Go button.  The result: Instead of entering 3.1415926535, he/she will have entered 314159265.35, and obtain somewhat different results than expected.

You may want to notify the user that a second decimal point has been entered.  Ignoring the second one (the same way the control ignores non-numeric chars) won't work as the user may have made the mistake when entering the first one.

----------


## MartinLiss

> Hi again.
> 
> I noticed that if a user enters a second decimal point, the first decimal point disappears.  
> 
> The user will probably not notice this event (I didn't) and will continue to happily enter numbers, and then click the Go button.  The result: Instead of entering 3.1415926535, he/she will have entered 314159265.35, and obtain somewhat different results than expected.
> 
> You may want to notify the user that a second decimal point has been entered.  Ignoring the second one (the same way the control ignores non-numeric chars) won't work as the user may have made the mistake when entering the first one.


I see what you are saying but there are a lot of possible mistakes and I think the user would find it annoying to be notified of each one.

----------


## rjbudz

I suppose it's a matter of opinion. 

I think entering a value of 3.1415926535 and having 314159265.35 entered instead would be far worse than asking if this is what the user intended. Entering two decimal points IS a mistake. To have the control decide the correct course of action (eliminate the first one) is presumptuous.

Users don't always recheck values they've entered, more so in this case because he/she knows non-numeric values will be ignored.  Not advising of a gross error defeats the purpose (MHO).

The vast majority of mistakes a user can make (I cant think of any others you havent anticipated) using this control have been eliminated.  That's what makes it so useful in the first place!

----------


## MartinLiss

Okay let me think about it.

----------


## rjbudz

sgrya1 makes a valid point regarding the second decimal point.  I think that is probably the way to go with it (again, MHO).

----------


## MartinLiss

> sgrya1 makes a valid point regarding the second decimal point.  I think that is probably the way to go with it (again, MHO).


I agree and I'll make the change in the next release.

----------


## rjbudz

Here's the code that does it from Calculator.zip:


VB Code:
Private Sub ButtonDecPoint_Click()
    If bError = False Then
        If iCurrentRadix = DECNUM Then
            If bEntered = False Then    '   Start of New Number
                bEntered = True
                OutputWindow.Text = "."
            Else                        '   Append
                If InStr(OutputWindow.Text, ".") = 0 Then   '   Make Sure Only 1 Decimal Point
                    OutputWindow.Text = OutputWindow.Text + "."
                End If
            End If
        End If
    End If
    OutputWindow.SetFocus
End Sub

----------


## sgrya1

In particular:


VB Code:
If InStr(OutputWindow.Text, ".") = 0 Then   '   Make Sure Only 1 Decimal Point
                    OutputWindow.Text = OutputWindow.Text + "."
                End If

----------


## rjbudz

Of course.  I included the entire method to make it easier to find and understand its use!   :Smilie:

----------


## MartinLiss

Updated to Version 1.9. Note that no change was made to the way a second decimal point is handled.

----------


## sgrya1

I've just moved to Europe where they use a comma "," as a decimal point rather than a "."

If I change the language to English it's fine but there's a problem with Polish for example.

You probably don't want to have to think about this but how do most windows apps understand that a comma acts as a decimal point.

The numberbox obviously doesn't allow it's use.

----------


## MartinLiss

I'll make a note about that for the future, thanks.

----------


## sgrya1

Martin,

Can you ignore my last request. When you press . on the numeric keypad it comes up as a comma. I think they are well aware that other countries use a . and that occasionally they need to use the keypad . rather than the numeric pad "."

I do have one more question though. How do I handle an empty numberbox.

if nbrbox. is empty then
if val(nbrbox) is nothing

if nbrbox.text = "" doesn't work as the contents aren't a string value.

----------


## MartinLiss

> Martin,
> 
> Can you ignore my last request. When you press . on the numeric keypad it comes up as a comma. I think they are well aware that other countries use a . and that occasionally they need to use the keypad . rather than the numeric pad "."
> 
> I do have one more question though. How do I handle an empty numberbox.
> 
> if nbrbox. is empty then
> if val(nbrbox) is nothing
> 
> if nbrbox.text = "" doesn't work as the contents aren't a string value.


I'm not 100% sure what you mean but the nfollowing works just fine.



```
Private Sub Command1_Click()
If NbrTextBox1.Text = "" Then
    MsgBox "error"
End If
End Sub
```

----------


## sgrya1

Oops. Ignore this.
My mistake.

----------


## dee-u

Hey martin, the ff. will break the decimal value, sorry I haven't had time to tinker on the solution...



```
Private Sub Command1_Click()
    'will display: -.1
    With NbrTextBox1
        .Text = "123456789"
        .SelStart = 0
        .SelText = "-"
        .SelStart = 0
        .SelText = "."
    End With
End Sub
```

----------


## MartinLiss

I'm not sure what you are saying the problem is. What is "ff"?

----------


## aleall

Please, try to digit the following number

*-123.4567*

 in the NumberBox at run-time in a form with MaxDecimals=2
and look what happens...

*-7123.45*  :EEK!:

----------


## MartinLiss

Updated to Version 1.10 which corrected the bug reported by aleall and added a DecimalSeperator property so that the user can decide to show numbers in the American (1234.56) or European (1234,56) style.

----------


## sgrya1

Thanks Martin!

----------


## aleall

Thank you   :Wink:

----------


## aleall

Another bug to fix?  :Sick:   :Alien Frog:  

if I digit 
123.45.

that's what happens

12345.

if I add two decimal numbers and another point (or comma) like so

12345.67.

number become

1234567.

... and so on.

----------


## MartinLiss

> Another bug to fix?   
> 
> if I digit 
> 123.45.
> 
> that's what happens
> 
> 12345.
> 
> ...


When a user enters a second decimal point I had to make a choice as to what to do. I chose to remove the first decimal point and that is what you see happening. Maybe it would have been better to just not allow the second one but I'll leave that for another day.

----------


## dee-u

> I'm not sure what you are saying the problem is. What is "ff"?


The code I posted will only show 1 numeric value after the decimal, I just coded the way I did it manually...

----------


## MartinLiss

Updated to Version 1.11 which corrects the bug reported by dee-u in post #46 and changes the way a second decimal seperator is processed as a result of aleall's post #52.

----------


## sgrya1

Martin,

Can I ask for another very minor thing to be adjusted?

When you change the border style to 0-None, the text shifts up very slightly and isn't aligned with other traditional textboxes. 

I manually adjusted this somehow in your control but I've forgotten how I did it.

----------


## MartinLiss

> Martin,
> 
> Can I ask for another very minor thing to be adjusted?
> 
> When you change the border style to 0-None, the text shifts up very slightly and isn't aligned with other traditional textboxes. 
> 
> I manually adjusted this somehow in your control but I've forgotten how I did it.


That's normal behavior. In other words it does align with a normal textbox whose border style is 0.

----------


## bluehairman

How can I make it so I can have more than one decimal put in?

----------


## MartinLiss

> How can I make it so I can have more than one decimal put in?


Can you show me an example of what you would like the number to look like?

----------


## bluehairman

An example would be for an IP.
example:
111.11.11.11

----------


## MartinLiss

Sorry but my control is meant to be used with numbers and that's not a number. You can use a MaskedEdit control for IPs.

----------


## bluehairman

I noticed a bug. When I have my Max value set to 5000.99 and I type in 8888888 in the box. The number changes to 500099, without the decimal. Which is a much higher number than the max in the first place.. I don't know how to fix this myself and I cannot even compile your source code..

----------


## MartinLiss

It doesn't do that for me. I did notice for the first time however that if I set the MaxValue to 5000.99 that the MinValue also gets set to 5000.99. What is your MinValue? And what do you mean when you say you can't compile my code?

----------


## bluehairman

Ok, I have it set to use a comma not a period. So in the Max value you would have to let the user put ###,## instead of erasing the , when entered in max value. Or change it to whatever decimal the user picks.
It works when I use a . for the decimal but not ,

And I get an error somewhere in the source code..

If you don't get what I say... Whenever a . is entered in the box and I only allow commas, it will delete the period so I end up with 500099

----------


## MartinLiss

> Ok, I have it set to use a comma not a period. So in the Max value you would have to let the user put ###,## instead of erasing the , when entered in max value. Or change it to whatever decimal the user picks.
> It works when I use a . for the decimal but not ,
> 
> And I get an error somewhere in the source code..
> 
> If you don't get what I say... Whenever a . is entered in the box and I only allow commas, it will delete the period so I end up with 500099


Okay, the comma/period code is new so there may well be a problem. I'll look into it but it won't be until tomorrow.

----------


## MartinLiss

Updated to Version 1.12 which corrects the problem with MaxValue and MinValue when the decimal seperator is a comma.

----------


## bluehairman

Hm.. I received your email but the updated version still seems to have that bug.

I get an error while trying to compile saying User Defined type not Defined.
It highlights this line:
Dim m_DataSource As StdDataFormat

I tried to fix the bug with this but I cannot test it..



> Private Sub txtNumberBox_KeyUp(KeyCode As Integer, Shift As Integer)
> ......
> On Error Resume Next
>     If CDbl(txtNumberBox.Text) > MaxValue Then
>         txtNumberBox.Text = MaxValue
>         If DecimalSeperator = Comma Then
>             txtNumberBox.Text = Replace(MaxValue, ".", ",")
>         End If
>     End If
> ...

----------


## MartinLiss

When you say "updated version" are you talking about the one I sent you or v1.12 that I posted here on the 25th? If you mean the former than you should try the v1.12.

----------


## sgrya1

Martin,

Do you know of a reason why v1.11 and v1.12 would be doing this when I try to compile?

When I try to make an executable I get an error (see attached) and all the number boxes have a diagonal hatch.

The program runs inside the IDE fine though.

Have you seen this before?

----------


## MartinLiss

The recent changes I made had to do with the difference in the way Europeans format numbers versus the way we in the US do. I'm sure that the problem involves either the System Locale or the Code Locale. Here's what MS has to say about it.

______________________________________________________________________

*System Locale vs. Code Locale*
The _system locale_ is the locale of the user who runs your program  it is used as a reference for user input and output and uses Control Panel settings provided by the operating system. The _code locale_ is always English/U.S. in Visual Basic, regardless of which international version you use. Code locale determines the programming language and all the locale-specific settings.
______________________________________________________________________

The change that I made was to change a Val() text-to-number conversion to a Cdbl() because from what I read Val() always assumes that the period is the decimal separator while CDbl use the system locale to determine the decimal separator.

To test the program I went to the control panel (Regional and Language Options|Regional Options) and changed my system locale from English (United States) to English (United Kingdom) and it worked fine. So assuming that your system locale is English (United Kingdom) I don't understand what's going on but I'll take another look at the program.

----------


## bluehairman

No, I am in the united states..
I would just rather the comma than the period but if it is too much trouble (or isn't what you'd like) I can deal with it just being a period.

Also do you know how to fix my error?

----------


## MartinLiss

I'm really confused about your post #67. What does StdDataFormat have to do with my program. Also at this point I believe my program is working properly. If it's not please tell me what it is doing that is wrong.

----------


## MartinLiss

Updated to Version 1.13.

Please see post #1 for changes and the decription of a known problem. Suggestions for fixing that problem are more than welcome.

----------


## MartinLiss

Updated to Version 1.14.

----------


## sgrya1

Here's a bug but not sure how easily it could be fixed.

If a decimal number is in the numberbox, when you highlight the contents to replace it's contents, you can't start off by pressing a decimal point (as there is already a decimal seperator in the cell).

----------


## MartinLiss

> Here's a bug but not sure how easily it could be fixed.
> 
> If a decimal number is in the numberbox, when you highlight the contents to replace it's contents, you can't start off by pressing a decimal point (as there is already a decimal seperator in the cell).


Thanks. After I do my taxes :Smilie:  I'll look into it.

----------


## MartinLiss

Updated to Version 1.15. Corrects problem reported in post #75.

----------


## MartinLiss

I made a small change to 1.15 so if anyone downloaded it then please download it again.

----------


## MartinLiss

Updated to Version 1.16

----------


## sgrya1

I have just installed my app on a computer with Vista. I get an error saying Component numberbox.ocx or one of its dependencies not correctly registered: a file is missing or invalid.
Are there any dependancy files that the numberbox.ocx has that may not be on vista computers?

I found this re Cryst32.ocx. I wonder if it's a similar situation or if I'm just failing something in the installation.




> The most common reason the Cryst32.ocx will not register is that it is missing one or more dependencies. 
> To register the crystl32.ocx make sure the following dependencies are present on your machine, then the OCX will register.
> 
> crystl32.ocx Dependencies
> ADVAPI32.DLL
> COMCTL32.DLL
> COMDLG32.DLL
> CRPE32.DLL
> GDI32.DLL
> ...

----------


## MartinLiss

I'm sorry but I have no experience with Vista. Perhaps you should create a new thread in the Visual Basic 6 and Earlier forum.

----------


## sgrya1

Sorry. My mistake. I had the incorrect .ocx version registered on the vista computer.

----------


## baja_yu

Found a bug. Run the Test project (all defaults), type 222.333 then go to the decimal point and delete it (backspace or delete), the text changes to 450.5

----------


## MartinLiss

I'm not sure what test project you mean, and by default the maximum decimals are set to 2, so you can't type 222.333, but even if I set MaxDecimals to 3 and I do as you say I get 222333.

----------


## baja_yu

I just downloaded the project from the first post, ran it (NumberBox.vbg) without changin anything. I happens every time. It could be the max decimal thing, I didn't change anything there either.

Oh. I just now noticed it has max and min value properties. It was changing based on that. In the attached project they are set to -19 and 450.5. That's why it was chaning it. My appologies.

----------


## MartinLiss

No problem.

----------


## Phantom1

This control is awesome and saves a lot of coding. It is great work. Thanks for it. Does it have a MaxLength property like for TextBox? How to allow commas to be typed in? E.g. 3,200.00 or 1,000,000.00, i.e. a comma separator for each three digits starting from the decimal point and going to the left, given that the decimal separator is a period.

----------


## MartinLiss

Thanks. 

The current version of the control does not allow adding commas as thousands separators so if you need them in a report or something my suggestion would be to use Format(). 

I'm not promising to make the change but if I were to allow the use of thousand separators would you you want to be able to type them in, or would you like the control to add them automatically?

----------


## Phantom1

An option to allow thousands separators, and then one to add them automatically or not (i.e. allow them to be typed).

----------

