|
Thanks for this, very useful but I have a smallish issue.
The example from the downloaded project does not allow you to enter a decimal the format like .xx but instead 0.xx. Small point I know but many users will input a fraction this way when entering large volumes od data.
|
|
|
|
|
Did you know you can do the following.....
1. Press the 2 number key.
2. Open notepad and press the - key.
3. Copy the "-" text into the clipboard.
4. Past the "-" text just after the 2 in the number edit box...
Chris
|
|
|
|
|
Thanks for notifying. I'm not actively following this project, but I will try to upload an update as soon as I can... by the way, did you find a solution to it yourself?
|
|
|
|
|
As a newbie to VB.net can I just say a BIG thank you for this code. It does exactly what I need.
I had attempted to write a similar routine but mine had loads of code and didn't work very well
I now understand how it can be done much better and simpler by taking a completely different approach.
Thank you so much.
Jem
|
|
|
|
|
Thanks for the complements. I'm glad I've helped you.
Hojjat
|
|
|
|
|
Hi Hojjat
I have a question...
I would like to use this code on a program that has quite a few different forms. On each form there are multiple textboxes, one of the forms has 12 textboxes all requiring the same numeric validation.
Would it be possible to have this code apply globally to all the textboxes on the form rather than having to list each one separately in the sub header?
If so how could I do this.
Even better would be to put the code into a module and have it apply to ALL textboxes in my program as none of them require anything other than numeric input.
Thank you for any help or advice you can give me.
Cheers
Jem
|
|
|
|
|
As I said before, my solution is for use when programmers decide to add this facility to their TextBoxes after they have added several TextBox controls, and added many other lines of code to their project based on these controls names.
However, if you are at the beginning of the design of your forms, it is more appropriate to use a user control which is a textbox accepting numeric values, rather than using the normal textbox control and adding the feature to it as I do in this article.
You can find such controls by searching in the internet, and even in the same codeproject web site:
http://www.codeproject.com/cs/miscctrl/HDNumericTextBox.asp
http://www.codeproject.com/vb/net/2gs_txtbx.asp
|
|
|
|
|
There are some errors when I input minus or paste a string including minus symbol, for example, I can paste "123-456-789" into the control.
|
|
|
|
|
I will fix it as soon as I can.
|
|
|
|
|
But I thought this control was only representing NUMERIC entries.
That kind of number, although made up of numeric symbols is not really a number.
That entry is more akin to needing something like a masked edit control.
My Blog[^] FFRF[^]
-- modified at 17:22 Saturday 25th February, 2006
|
|
|
|
|
>> That kind of number, although made up of numeric symbols is not really a number.
I'm not sure what you mean by the above statement. Afterall, TextBox.Text is always a string, and what I offer here, is to limit this string to contain numeric values only.
|
|
|
|
|
If the aim of your text box is to allow only numeric values only then you have to consider exactly what IS a number.
For example:
$4.00 is a number
50% is a number
2 is a number
5:00pm could also be considered a number
All these above examples are 'numbers' because they represent a numeric AMOUNT type of a construct.
The example that the other person gave of '123-456-789' really does not represent a numeric amount, it represents a pattern of characters that just in this case happen to all be characters that are allowed in numeric display.
Maybe I am over thinking this a bit, and if I am I am sorry to muddy the discussion here, but I think if your controls focus is to only allow numeric values then you have to consider what really IS a numeric value. Not just the individual characters but what they represent as a whole when entered in. This has a larger meaning than just creating a control that only allows numeric type characters in.
If you are only allowing numeric type characters then you have to take into account ALL the different numeric characters and I am not that sure of the overall usefulness of the control at that point.
As one further example... IPV4 addresses allow for 4 groups of numbers, each separated by a '.'. Each characters is considered a numeric type character but as whole and IP address is not considered a numeric value. Should your control allow and validate this as a proper value? If it does then it has moved from being a numeric value text box into the realm of an IP address text box.
Just trying to push home the fact that once you widen the scope of your control very wide then you open yourself up to tons of problems. If a person wants to enter in an IP address then they should use a control specifically for that type of entry. If a person wants to enter a numeric value (dollars, pounds, percents, etc...) then they use yours here. If they want to end in something else then maybe they use another. Just trying to say that you need to keep your scope on point here and be ready and willing to tell people requesting features and pointing out what 'they' think are bugs, that their request doe snot fit the scope of your control and for what reasons you feel that way. This is one reason why there are so many controls out there that end up no good. They try to be all things to all people and in the end never do anything very well.
My Blog[^] FFRF[^]
-- modified at 13:19 Sunday 26th February, 2006
|
|
|
|
|
Well in a mathematical point of view (as far as I know), $4.00 is not a number, but a number and a symbol to its left! Or an IP address is not "a" number, but a set of "four" numbers separated by a decimal sign.
However, in order to make sure such confusion is not going to happen again, I'm modifying the text of article to clearly define what the textboxes are going to do.
I hope my article to be a good start point for others to create their own controls meeting their specific needs.
Thanks for your attention
|
|
|
|
|
Just to add my 2 penneth worth....
$4.00 isnt a number its an amount of currency. 4.00 is the numeric part
Good code piece, perhaps it would be an idea to create a currencyTextBox, percentageTextBox etc??
Anyways, thanks for the code..
|
|
|
|
|
That is a point of view too. Thanks for your complements. I think those kinds of textboxes are made by other people before as seperate user controls. There are numeric textbox user controls doing what I offered here too. What I meant to offer here, was a way to prevent using a user control.
|
|
|
|
|
The source solution won't open in vs2003.
Gary Minor
|
|
|
|
|
VS2005 solutions won't open in 2003. You may still be able to use the classes tho.
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
Exactly. I wrote the code in VB2005 but the class can be used in VS2003 as well. It uses features available in .NET framework 1.0
I'm aware of no 2005 to 2003 convertor, or I'd post a link to it here.
|
|
|
|
|
It works fine but what's happen if there is a coma in the pasted text? You don't get the right number...
can we have theese changes ?
Public Class TextBoxOnPaste<br />
<br />
Inherits NativeWindow<br />
<br />
Private tb As TextBox<br />
<br />
Private Sub New()<br />
<br />
End Sub<br />
<br />
Public Sub New(ByVal tb As TextBox)<br />
<br />
Me.tb = tb<br />
<br />
Me.AssignHandle(tb.Handle)<br />
<br />
End Sub<br />
<br />
Private Const WM_PASTE As Integer = &H302<br />
<br />
Protected Overrides Sub WndProc(ByRef m As Message)<br />
<br />
Dim SeparateurDecimal As String = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator<br />
<br />
'With every key press, click, key-combination press, etc a Message is sent to the<br />
<br />
' window. You need to read about Win32 programming if you don't understand it.<br />
<br />
Select Case m.Msg<br />
<br />
Case WM_PASTE<br />
<br />
'User has tried a way to paste something, like SHIFT+INSERT or<br />
<br />
' right-click context menu...<br />
<br />
If Clipboard.GetDataObject.GetDataPresent(DataFormats.Text) Then<br />
<br />
'What user has tried to paste is a piece of text...<br />
<br />
Dim str As String = Clipboard.GetDataObject.GetData(DataFormats.Text)<br />
<br />
'si on colle un nombre décimal avec une virgule : ça marche aussi !<br />
<br />
If InStr(str, ",") <> 0 Then<br />
<br />
Replace(str, ",", SeparateurDecimal)<br />
<br />
ElseIf InStr(str, ".") <> 0 Then<br />
<br />
Replace(str, ".", SeparateurDecimal)<br />
<br />
End If<br />
<br />
'si ça commence par le séparateur on ajoute 0<br />
<br />
If InStr(str, ",") = 1 Or InStr(str, ".") = 1 Then<br />
<br />
str = "0" & str<br />
<br />
End If<br />
<br />
Dim NewVal As String<br />
<br />
NewVal = Mid(tb.Text, 1, tb.SelectionStart) & str & Mid(tb.Text, tb.SelectionStart + tb.SelectionLength + 1, Len(tb.Text))<br />
<br />
'NewVal will contain the future value of the textbox, if we would let<br />
<br />
' what user wanted to paste to actually paste there...<br />
<br />
If IsNumeric(NewVal) Then<br />
<br />
' The result will be a numeric value. So go ahead and paste it!<br />
<br />
tb.SelectedText = str<br />
<br />
End If<br />
<br />
' We're done, so we exit the sub (not letting the default WndProc() to<br />
<br />
' paste the original string user tried to paste.<br />
<br />
Exit Sub<br />
<br />
End If<br />
<br />
End Select<br />
<br />
'In situations other than what we handled, the default WndProc() needs to be run<br />
<br />
MyBase.WndProc(m)<br />
<br />
End Sub<br />
<br />
End Class
et pour la form1 where there are 2 txtbox and one button and one label
Public Class Form1<br />
<br />
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load<br />
'Add onPaste handles when the form loads<br />
Dim onPaste1 As New TextBoxOnPaste(Me.TextBox1)<br />
Dim onPaste2 As New TextBoxOnPaste(Me.TextBox2)<br />
End Sub<br />
<br />
<br />
Private Sub numericTextboxKeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress, TextBox2.KeyPress<br />
Dim tb As TextBox = CType(sender, TextBox)<br />
Dim SeparateurDecimal As String = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator<br />
If IsNumeric(e.KeyChar) Then<br />
'If adding the character to the end of the current TextBox value results in<br />
' a numeric value, go on. Otherwise, set e.Handled to True, and don't let<br />
' the character to be added.<br />
e.Handled = Not IsNumeric(tb.Text & e.KeyChar)<br />
ElseIf e.KeyChar = "." Or e.KeyChar = "," Then<br />
e.KeyChar = ChrW(Asc(SeparateurDecimal))<br />
'For the decimal character (.) we need a different rule:<br />
'If adding a decimal to the end of the current value of the TextBox results<br />
' in a numeric value, it can be added. If not, this means we already have a<br />
' decimal in the TextBox value, so we only allow the new decimal to sit in<br />
' when it is overwriting the previous decimal.<br />
'If Not (tb.SelectedText = "." Or IsNumeric(tb.Text & e.KeyChar)) Then ==> replaced by<br />
If Not (tb.SelectedText = SeparateurDecimal Or IsNumeric(tb.Text & e.KeyChar)) Then<br />
e.Handled = True<br />
End If<br />
ElseIf Not Char.IsControl(e.KeyChar) Then<br />
'IsControl is checked, because without that, keys like BackSpace couldn't<br />
' work correctly.<br />
e.Handled = True<br />
End If<br />
End Sub<br />
<br />
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click<br />
Dim result As Double<br />
Dim Nbre1 As Double<br />
Dim Nbre2 As Double<br />
If TextBox1.Text <> "" And TextBox2.Text <> "" Then<br />
Nbre1 = TextBox1.Text<br />
Nbre2 = TextBox2.Text<br />
result = Nbre1 * Nbre2<br />
Label2.Text = result<br />
End If<br />
End Sub<br />
End Class<br />
quisnam igitur sanus ?
|
|
|
|
|
Thanks for your attention.
In order to make the class usage easier for everyone, I changed the class code to remove comas.
|
|
|
|
|
'Remove all appearances of coma<br />
str = Replace(str, ",", "")
I think it's not a good solution... Sometimes people have the coma for the decimal separator ... You have to test this before replace any coma by nothing because 8,5 * 4,1 will not give the same result than 85 * 41.(in case you use the txtbox input to calculate!) I tried to make the change in my first post : i am a newbie in vb2005 ! So i think this is not an elegant solution but it works the good way !
I think this numeric txtbox could be even better if the code in form1Sub numericTextboxKeyPress was handle in the module too : i remember to have seen (in vb6 ) here http://www.vbfrance.com/codes/TEXTBOX-NUMERIQUE_578.aspx[^] a way to do that.
quisnam igitur sanus ?
|
|
|
|
|
Well as far as I know, using coma for a decimal is illegal, at least in VB.net
The use of coma in numbers is indeed for seperating the digits in large numbers to ease their reading, like this: 2,397,546.81 and not as a alternative to the decimal.
|
|
|
|
|
I think you are right for english setting computers but not for french setting type where numbers could be write like this :
a) 2 397 546.81 or like this
b) 2 397 546,81
quisnam igitur sanus ?
|
|
|
|
|
Oops. I didn't notice that. Well I have to change the article a bit. I will put that as a notice there. After all, this is Microsoft's mistake not to put a multiple locale Numeric Textbox in the controls. What I (and others) do is to somehow work around this mistake
|
|
|
|
|
It's comma
|
|
|
|