Answered by:
Overflow on NumericUpDown

Question
-
I have a client who, believe it or not, wants integers that are 28 digits long (the maximum allowed in the decimal type). When testing, I entered a longer integer, which exceeded the allowable range of the decimal type. Immediately I got an overflow exception.
I looked at the events associated with the NumericUpDown control and saw nothing that I could use to intercept this overflow. As you know the NumericUpDown control returns a decimal value.
Is there no way to intercept this so the value gets set to a valid high value; as it is now the program will simply crash??
Thanks in advance for any help.
Michael Bate
- Moved by CoolDadTx Monday, November 23, 2015 2:53 PM Winforms related
Sunday, November 22, 2015 11:29 PM
Answers
-
Hello,
For a number that long it would seem prudent to also consider a TextBox if you are receiving an overflow even thou when I set the max to a value below the overflow limit the NumericUpDown abides by the max value set.
If we look at preventing this internally with Maximum set we never trigger a true for the condition below.
Public Class MyNumericUpDown Inherits NumericUpDown ''' <summary> ''' We can do this in the hosting form too but when maximum is set ''' it is a moot point, we never get a true on the if statement even in ''' Framework 2. ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub MyNumericUpDown_ValueChanged(sender As Object, e As EventArgs) Handles Me.ValueChanged If Value > 9999999999999999999999999999D Then Value = Maximum End If End Sub End Class
Using the following custom TextBox, set Max characters via MaxLength, set AllowDecimals then to return the value use DecimalValue property.
Compile this in your project
Imports System.ComponentModel Public Class numericTextbox Inherits TextBox Const WM_PASTE As Integer = &H302 <Category("Behavior"), _ Description("Should decimals be allowed"), _ DefaultValue(GetType(Integer), "1")> _ Public Property AllowDecimals As Boolean <Browsable(False)> Public ReadOnly Property DecimalValue() As Decimal Get Return CDec(Text) End Get End Property Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs) Dim value As String = Me.Text value = value.Remove(Me.SelectionStart, Me.SelectionLength) value = value.Insert(Me.SelectionStart, e.KeyChar) If AllowDecimals Then e.Handled = CBool(value.LastIndexOf("-") > 0) _ Or Not (Char.IsControl(e.KeyChar) OrElse Char.IsDigit(e.KeyChar) OrElse (e.KeyChar = "."c And Not _ Me.Text.Contains(".") Or e.KeyChar = "."c And _ Me.SelectedText.Contains(".")) OrElse (e.KeyChar = "-"c And Me.SelectionStart = 0)) Else e.Handled = CBool(value.LastIndexOf("-") > 0) _ Or Not (Char.IsControl(e.KeyChar) OrElse Char.IsDigit(e.KeyChar) OrElse (e.KeyChar = "-"c And Me.SelectionStart = 0)) End If MyBase.OnKeyPress(e) End Sub Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) If m.Msg = WM_PASTE Then Dim value As String = Me.Text value = value.Remove(Me.SelectionStart, Me.SelectionLength) value = value.Insert(Me.SelectionStart, Clipboard.GetText) If AllowDecimals Then Dim result As Decimal = 0 If Not Decimal.TryParse(value, result) Then Return End If Else Dim result As Integer = 0 If Not Integer.TryParse(value, result) Then Return End If End If End If MyBase.WndProc(m) End Sub End Class
Note before continuing the custom control disallows pasting invalid values from the Windows clipboard.
Now add the control to a form and set MaxLength to say 28, set AllowDecimals to true e.g.
NumericTextbox1.MaxLength = 28 NumericTextbox1.AllowDecimals = True
At any time get the text as a decimal
NumericTextbox1.DecimalValue
Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my webpage under my profile but do not reply to forum questions.
Microsoft Developer tools
Developer’s Guide to Windows 10 video series- Edited by KareninstructorMVP Saturday, November 28, 2015 10:48 AM ...
- Marked as answer by Herro wongMicrosoft contingent staff Tuesday, December 1, 2015 1:23 AM
Saturday, November 28, 2015 10:47 AM -
I thought that I replied to this before.
The NumericUpDown control appears to convert the value entered by the user to decimal before comparing with the Maximum and Minimum and therefore raises an overflow exception before these comparisons. I am using .Net Framework 2.0. Maybe a later version fixes this, but the Maximum value does not deal with the problem when the user enters a huge value.
I was unable to replicate the issue on Win7 64 bit system with app compiled to .Net 2.0 and either x86, x64 or AnyCPU.
Like Matthew LEAN . D did I used Decimal.MinValue or Decimal.MaxValue for the minimum or maximum setting as when I tried to set those to either -79228162514264337593543950335 or 79228162514264337593543950335 an overflow occured. Even if I tried using
CDec(-79228162514264337593543950335) or CDec(79228162514264337593543950335) an overflow occured. However using what Matthew LEAN .D used worked and I could paste from -79228162514264337593543950335 to 79228162514264337593543950335 in the NumericUpDown window and the NumericUpDown would accept that with no problem. Selecting the up arrow on the spinbox with the max value in the NumericUpDown window and nothing would happen but selecting the down arrow and negative increment would occur. Same with pasting negative max value in window except up arrow would increment but not down arrow.
No matter how many digits were typed or pasted into the NumericUpDown window no issue occured with it. I even pasted text "Win7 64 bit system" into the window and nothing happened except the last value displayed in the window incremented when I selected an arrow in the spinbox.
Also you use the term Long Integer and entering same. Was that via the NumericUpDown text window or via code attempting to set the NumericUpDown1 value to a Long Integer value?
Option Strict On Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2))) NumericUpDown1.Minimum = Decimal.MinValue NumericUpDown1.Maximum = Decimal.MaxValue NumericUpDown1.DecimalPlaces = 2 NumericUpDown1.Increment = 1 End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click MessageBox.Show(Decimal.MaxValue.ToString & vbCrLf & Decimal.MinValue.ToString) End Sub End Class
Update: The below code works too.
Option Strict Off Option Infer Off Option Explicit Off Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2))) NumericUpDown1.Minimum = CDec("-79228162514264337593543950335") NumericUpDown1.Maximum = CDec("79228162514264337593543950335") NumericUpDown1.DecimalPlaces = 2 NumericUpDown1.Increment = 1 End Sub Dim Temp As String = "79228162514264337593543950335" Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click MessageBox.Show(Decimal.MaxValue.ToString & vbCrLf & Decimal.MinValue.ToString) NumericUpDown1.Value = CDec(Temp) End Sub End Class
La vida loca
- Edited by Mr. Monkeyboy Saturday, November 28, 2015 3:00 PM
- Marked as answer by Herro wongMicrosoft contingent staff Tuesday, December 1, 2015 1:23 AM
Saturday, November 28, 2015 2:41 PM
All replies
-
Can't you set the Maximum property on the control to stop it overflowing?
And by the way, are you sure that a NumericUpDown is a good idea in this situation? I find it hard to imagine a user pressing the up arrow for a few thousand years to go through 28 digits.
Monday, November 23, 2015 12:35 AM -
Well I believe the Decimal type can represent 29 digits ahead of the decimal point according to Decimal Structure from positive 79,228,162,514,264,337,593,543,950,335 to negative 79,228,162,514,264,337,593,543,950,335. If you set the minimum value to 0 or if allowed -79228162514264337593543950335 and maximum value to 79228162514264337593543950335 then there should be no issue.
The increment value would need to be considered also. I've never tested to see if a decimal can be entered by typing in the NumericUpDown with the increment set to 1 but entering a decimal value of perhaps 1.0000000002 or something to see what would happen.
La vida loca
- Edited by Mr. Monkeyboy Monday, November 23, 2015 12:54 AM
- Proposed as answer by Herro wongMicrosoft contingent staff Thursday, November 26, 2015 5:19 AM
Monday, November 23, 2015 12:46 AM -
HI.
there is not crash happen on my side.
input
-79228162514264337593543950335 or
79228162514264337593543950335this.numericUpDown1.Increment = 0; this.numericUpDown1.Maximum = decimal.MaxValue; this.numericUpDown1.Minimum = decimal.MinValue; this.numericUpDown1.Controls[0].Visible = false;//hide the updown arrow this.numericUpDown1.InterceptArrowKeys = false; this.numericUpDown1.DecimalPlaces = 4;
...
DON'T TRY SO HARD,THE BEST THINGS COME WHEN YOU LEAST EXPECT THEM TO.
- Edited by Matthew LEAN . D Monday, November 23, 2015 3:10 AM
- Proposed as answer by Herro wongMicrosoft contingent staff Thursday, November 26, 2015 5:19 AM
Monday, November 23, 2015 3:09 AM -
I thought that I replied to this before.
The NumericUpDown control appears to convert the value entered by the user to decimal before comparing with the Maximum and Minimum and therefore raises an overflow exception before these comparisons. I am using .Net Framework 2.0. Maybe a later version fixes this, but the Maximum value does not deal with the problem when the user enters a huge value.
Thursday, November 26, 2015 5:30 AM -
Hi.
decimal type has precision 28-29 significant digits
if you need more bigger precision
use
System.Numerics.BigInteger and parse TextBox's Text
https://msdn.microsoft.com/en-us/library/vstudio/system.numerics.biginteger(v=vs.100).aspx
DON'T TRY SO HARD,THE BEST THINGS COME WHEN YOU LEAST EXPECT THEM TO.
- Edited by Matthew LEAN . D Friday, November 27, 2015 2:45 AM
Friday, November 27, 2015 2:41 AM -
Hello,
For a number that long it would seem prudent to also consider a TextBox if you are receiving an overflow even thou when I set the max to a value below the overflow limit the NumericUpDown abides by the max value set.
If we look at preventing this internally with Maximum set we never trigger a true for the condition below.
Public Class MyNumericUpDown Inherits NumericUpDown ''' <summary> ''' We can do this in the hosting form too but when maximum is set ''' it is a moot point, we never get a true on the if statement even in ''' Framework 2. ''' </summary> ''' <param name="sender"></param> ''' <param name="e"></param> ''' <remarks></remarks> Private Sub MyNumericUpDown_ValueChanged(sender As Object, e As EventArgs) Handles Me.ValueChanged If Value > 9999999999999999999999999999D Then Value = Maximum End If End Sub End Class
Using the following custom TextBox, set Max characters via MaxLength, set AllowDecimals then to return the value use DecimalValue property.
Compile this in your project
Imports System.ComponentModel Public Class numericTextbox Inherits TextBox Const WM_PASTE As Integer = &H302 <Category("Behavior"), _ Description("Should decimals be allowed"), _ DefaultValue(GetType(Integer), "1")> _ Public Property AllowDecimals As Boolean <Browsable(False)> Public ReadOnly Property DecimalValue() As Decimal Get Return CDec(Text) End Get End Property Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs) Dim value As String = Me.Text value = value.Remove(Me.SelectionStart, Me.SelectionLength) value = value.Insert(Me.SelectionStart, e.KeyChar) If AllowDecimals Then e.Handled = CBool(value.LastIndexOf("-") > 0) _ Or Not (Char.IsControl(e.KeyChar) OrElse Char.IsDigit(e.KeyChar) OrElse (e.KeyChar = "."c And Not _ Me.Text.Contains(".") Or e.KeyChar = "."c And _ Me.SelectedText.Contains(".")) OrElse (e.KeyChar = "-"c And Me.SelectionStart = 0)) Else e.Handled = CBool(value.LastIndexOf("-") > 0) _ Or Not (Char.IsControl(e.KeyChar) OrElse Char.IsDigit(e.KeyChar) OrElse (e.KeyChar = "-"c And Me.SelectionStart = 0)) End If MyBase.OnKeyPress(e) End Sub Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message) If m.Msg = WM_PASTE Then Dim value As String = Me.Text value = value.Remove(Me.SelectionStart, Me.SelectionLength) value = value.Insert(Me.SelectionStart, Clipboard.GetText) If AllowDecimals Then Dim result As Decimal = 0 If Not Decimal.TryParse(value, result) Then Return End If Else Dim result As Integer = 0 If Not Integer.TryParse(value, result) Then Return End If End If End If MyBase.WndProc(m) End Sub End Class
Note before continuing the custom control disallows pasting invalid values from the Windows clipboard.
Now add the control to a form and set MaxLength to say 28, set AllowDecimals to true e.g.
NumericTextbox1.MaxLength = 28 NumericTextbox1.AllowDecimals = True
At any time get the text as a decimal
NumericTextbox1.DecimalValue
Please remember to mark the replies as answers if they help and unmark them if they provide no help, this will help others who are looking for solutions to the same or similar problem. Contact via my webpage under my profile but do not reply to forum questions.
Microsoft Developer tools
Developer’s Guide to Windows 10 video series- Edited by KareninstructorMVP Saturday, November 28, 2015 10:48 AM ...
- Marked as answer by Herro wongMicrosoft contingent staff Tuesday, December 1, 2015 1:23 AM
Saturday, November 28, 2015 10:47 AM -
I thought that I replied to this before.
The NumericUpDown control appears to convert the value entered by the user to decimal before comparing with the Maximum and Minimum and therefore raises an overflow exception before these comparisons. I am using .Net Framework 2.0. Maybe a later version fixes this, but the Maximum value does not deal with the problem when the user enters a huge value.
I was unable to replicate the issue on Win7 64 bit system with app compiled to .Net 2.0 and either x86, x64 or AnyCPU.
Like Matthew LEAN . D did I used Decimal.MinValue or Decimal.MaxValue for the minimum or maximum setting as when I tried to set those to either -79228162514264337593543950335 or 79228162514264337593543950335 an overflow occured. Even if I tried using
CDec(-79228162514264337593543950335) or CDec(79228162514264337593543950335) an overflow occured. However using what Matthew LEAN .D used worked and I could paste from -79228162514264337593543950335 to 79228162514264337593543950335 in the NumericUpDown window and the NumericUpDown would accept that with no problem. Selecting the up arrow on the spinbox with the max value in the NumericUpDown window and nothing would happen but selecting the down arrow and negative increment would occur. Same with pasting negative max value in window except up arrow would increment but not down arrow.
No matter how many digits were typed or pasted into the NumericUpDown window no issue occured with it. I even pasted text "Win7 64 bit system" into the window and nothing happened except the last value displayed in the window incremented when I selected an arrow in the spinbox.
Also you use the term Long Integer and entering same. Was that via the NumericUpDown text window or via code attempting to set the NumericUpDown1 value to a Long Integer value?
Option Strict On Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2))) NumericUpDown1.Minimum = Decimal.MinValue NumericUpDown1.Maximum = Decimal.MaxValue NumericUpDown1.DecimalPlaces = 2 NumericUpDown1.Increment = 1 End Sub Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click MessageBox.Show(Decimal.MaxValue.ToString & vbCrLf & Decimal.MinValue.ToString) End Sub End Class
Update: The below code works too.
Option Strict Off Option Infer Off Option Explicit Off Public Class Form1 Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load Me.Location = New Point(CInt((Screen.PrimaryScreen.WorkingArea.Width / 2) - (Me.Width / 2)), CInt((Screen.PrimaryScreen.WorkingArea.Height / 2) - (Me.Height / 2))) NumericUpDown1.Minimum = CDec("-79228162514264337593543950335") NumericUpDown1.Maximum = CDec("79228162514264337593543950335") NumericUpDown1.DecimalPlaces = 2 NumericUpDown1.Increment = 1 End Sub Dim Temp As String = "79228162514264337593543950335" Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click MessageBox.Show(Decimal.MaxValue.ToString & vbCrLf & Decimal.MinValue.ToString) NumericUpDown1.Value = CDec(Temp) End Sub End Class
La vida loca
- Edited by Mr. Monkeyboy Saturday, November 28, 2015 3:00 PM
- Marked as answer by Herro wongMicrosoft contingent staff Tuesday, December 1, 2015 1:23 AM
Saturday, November 28, 2015 2:41 PM