logo  VB.Net - Extended Numeric Up Down
This Chapter
User Controls
Date Picker
Roll a Dice
Integer Picker
Integer Up/Down
Chapters
Home Page
Colours, RGB
Computer Specifications
Dates&Times
Disk Drives
Files
Folders
GPS and OS Ref
VB.Net Forms
Image Files
If & Select
List/Array
Mathematics
NuGet
Sound
String Functions
Sun and Moon
User Controls
Validation
DigitalDan Sites
My Other Sites
Contact Site

Note
Some pages
may contain
inaccuracies
Hits=4
Note
When adding this control to your form, you should either use the name CtlNum or rename the class to match the name you selected.

 
Number Up Down

Picture of this control

This control is intended for integer numbers. VB.Net has a built in numeric up/down control which is ideal for small numbers, however, this contol offers an alternative aimed at larger integers. Each digit (and +/- if present) can be scrolled separately to speed up number selection.

 
Here is the full code for the CtlNum contol. The key properties available to your project are explained at the end of this page.

Option Strict On
Option Explicit On
Imports System.ComponentModel
' Notes
' +/- sign only visible if minValue < 0 and value <> 0
' Size of control automatically adjusts for +/- visibilty, max number of digits and font
Public Class CtlNum
 Private ListButU As List(Of Button) = InitListBut()
 Private ListLabel As List(Of Label) = InitListLabel()
 Private ListButD As List(Of Button) = InitListBut()
 Private valueString As String = "+0000"
 Private prevValue As Integer = 0
 Private _font As Font = Me.Font
 Private _value As Integer = 0
 Private _minValue As Integer = -9999
 Private _maxValue As Integer = 9999
 Private _butColor As Color = Color.Gray
 Private _textForeColor As Color = ListLabel.Item(0).ForeColor
 Private _textBackColor As Color = SystemColors.Info
 Public Event A_ValueChanged()
 Private Sub CtlNum_Load(sender As Object, e As EventArgs) Handles MyBase.Load
  Me.Enabled = False
  LoadButtonsLabels()
  ShowValue()
  Me.Enabled = True
 End Sub
 Private Function InitListBut() As List(Of Button)
  Dim ret As New List(Of Button)
  For i As Integer = 0 To 10
   ret.Add(New Button)
  Next
  Return ret
 End Function
 Private Function InitListLabel() As List(Of Label)
  Dim ret As New List(Of Label)
  For i As Integer = 0 To 10
   ret.Add(New Label)
  Next
  Return ret
 End Function
 Private Sub LoadButtonsLabels()
  Dim labelSize As Size = TextRenderer.MeasureText("8", _font)
  labelSize = New Size(labelSize.Width + 2, labelSize.Height + 2)
  Dim h As Integer = CInt(Math.Round(Math.Ceiling(labelSize.Height / 4)))
  If h < 6 Then h = 6
  Dim buttonsize As New Size(labelSize.Width, h)
  '  buttonsize = labelSize
  Dim gap As Integer = 3
  Dim digits As Integer = GetDigitCount()
  Dim mask As String = Mid("0000000000", 1, digits)
  valueString = Math.Abs(_value).ToString(mask)
  If _minValue < 0 Then
   If _value < 0 Then
    valueString = "-" & valueString
   Else
    valueString = "+" & valueString
   End If
  End If
  Dim t1, t2, t3, t4, l As Integer
  t1 = gap
  t2 = t1 + gap + buttonsize.Height
  t3 = t2 + gap + labelSize.Height
  t4 = t3 + gap + buttonsize.Height
  l = gap
  ListButU.Clear()
  ListLabel.Clear()
  ListButD.Clear()
  Me.Controls.Clear()
  Dim bu, bd As New Button
  Dim la As New Label
  For i As Integer = 0 To digits
   bu = New Button With {
    .AutoSize = False,
    .BackColor = _butColor,
    .FlatStyle = FlatStyle.Flat,
    .Font = _font,
    .Location = New Point(l, t1),
    .Name = "ButU" & i.ToString,
    .Size = buttonsize,
    .Text = String.Empty,
    .Visible = (i < valueString.Length)
   }
   ListButU.Add(bu)
   Me.Controls.Add(ListButU.Item(ListButU.Count - 1))
   la = New Label With {
    .AutoSize = False,
    .BorderStyle = BorderStyle.FixedSingle,
    .Font = _font,
    .Location = New Point(l, t2),
    .Name = "Lab" & i.ToString,
    .Size = labelSize,
    .Text = i.ToString,
    .ForeColor = _textForeColor,
    .BackColor = _textBackColor,
    .TextAlign = ContentAlignment.MiddleCenter,
    .Visible = (i < valueString.Length)
   }
   ListLabel.Add(la)
   Me.Controls.Add(ListLabel.Item(ListLabel.Count - 1))
   bd = New Button With {
    .AutoSize = False,
    .BackColor = _butColor,
    .FlatStyle = FlatStyle.Flat,
    .Font = _font,
    .Location = New Point(l, t3),
    .Name = "ButD" & i.ToString,
    .Size = buttonsize,
    .Text = String.Empty,
    .Visible = (i < valueString.Length)
   }
   ListButD.Add(bd)
   Me.Controls.Add(ListButD.Item(ListButD.Count - 1))
   l += gap + labelSize.Width
  Next
  For i As Integer = 0 To ListLabel.Count - 1
   AddHandler ListButU.Item(i).Click, AddressOf ButtonHandler
   AddHandler ListButD.Item(i).Click, AddressOf ButtonHandler
  Next
  If _minValue < 0 Then digits += 1
  Me.Size = New Size(2 + gap + (digits * (gap + labelSize.Width)), t4 + 2)
  Me.BorderStyle = BorderStyle.FixedSingle
 End Sub
 Private Function GetDigitCount() As Integer
  Dim minStr As String = _minValue.ToString.Replace("-"c, String.Empty)
  Dim maxStr As String = _maxValue.ToString.Replace("-"c, String.Empty)
  Return Math.Max(minStr.Length, maxStr.Length)
 End Function
 Private Sub ShowValue()
  If _value < _minValue Then _value = _minValue
  If _value > _maxValue Then _value = _maxValue
  Dim digits As Integer = GetDigitCount()

  For i As Integer = 0 To digits - 1
   If ListLabel.Item(i).Text = "+" OrElse ListLabel.Item(i).Text = "-" Then
    ListButU.Item(i).Visible = (_maxValue > 0)
    ListButD.Item(i).Visible = (_maxValue > 0)
    Continue For
   End If
  Next
  Dim mask As String = Mid("0000000000", 1, digits)
  valueString = Math.Abs(_value).ToString(mask)
   If _minValue < 0 Then
    Select Case _value
     Case < 0
      valueString = "-" & valueString
     Case 0
      valueString = " " & valueString
     Case > 0
      valueString = "+" & valueString
    End Select
   End If
  For i As Integer = 0 To valueString.Length - 1
   ListLabel.Item(i).Text = Mid(valueString, i + 1, 1)
   If "+ -".Contains(ListLabel.Item(i).Text) Then
    Continue For
   End If
   ListButU.Item(i).Visible = (_value < _maxValue)
   ListButD.Item(i).Visible = (_value > _minValue)
  Next
  If "+-".Contains(ListLabel.Item(0).Text) Then
   Dim tf As Boolean = (_minValue < 0 AndAlso _maxValue > 0)
   ListButU.Item(0).Visible = tf
   ListButD.Item(0).Visible = tf
  End If
  If ListLabel.Item(0).Text = " " Then
   ListButU.Item(0).Visible = False
   ListButD.Item(0).Visible = False
  End If
  If prevValue <> _value Then
   prevValue = _value
   RaiseEvent A_ValueChanged()
  End If
 End Sub
 Private Sub ButtonHandler(sender As Object, e As EventArgs)
  Me.Enabled = False
  Dim but As Button = CType(sender, Button)
  Dim sendername As String = but.Name
  Dim butnum As Integer
  If Not Integer.TryParse(Mid(sendername, 5), butnum) Then butnum = 0
  If "+-".Contains(ListLabel.Item(butnum).Text) Then
   _value = 0 - _value
   ShowValue()
   Me.Enabled = True
   Exit Sub
  End If
  Dim mult As Integer = 1
  For i As Integer = ListLabel.Count - 1 To 0 Step -1
   If ListLabel.Item(i).Visible = False Then
    Continue For
   End If
   If i = butnum Then
    Exit For
   End If
   mult *= 10
  Next
  If Mid(sendername, 4, 1) = "U" Then
   _value += mult
  Else
   _value -= mult
  End If
  ShowValue()
  Me.Enabled = True
 End Sub
 Private Function NotTransparent(c As Color) As Color
  Return Color.FromArgb(255, c.R, c.G, c.B)
 End Function
 <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
 Public Property A_Value As Integer
  Get
   Return _value
  End Get
  Set(value As Integer)
   Me.Enabled = False
   Dim v As Integer = value
   If v < _minValue Then v = _minValue
   If v > _maxValue Then v = _maxValue
   _value = v
   ShowValue()
   Me.Enabled = True
  End Set
 End Property
 <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
 Public Property A_MinValue As Integer
  Get
   Return _minValue
  End Get
  Set(value As Integer)
   Me.Enabled = False
   Dim v As Integer = value
   If v > _maxValue Then _maxValue = v
   If v > _value Then _value = v
   _minValue = v
   LoadButtonsLabels()
   ShowValue()
   Me.Enabled = True
  End Set
 End Property
 <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
 Public Property A_MaxValue As Integer
  Get
   Return _maxValue
  End Get
  Set(value As Integer)
   Me.Enabled = False
   Dim v As Integer = value
   If v < _minValue Then _minValue = v
   If v < _value Then _value = v
   _maxValue = v
   LoadButtonsLabels()
   ShowValue()
   Me.Enabled = True
  End Set
 End Property
 <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
 Public Property A_Font As Font
  Get
   Return _font
  End Get
  Set(value As Font)
   Me.Enabled = False
   Dim fs As Single = value.Size
   If fs < 10 Then fs = 10
   If fs > 50 Then fs = 50
   _font = New Font(value.Name, fs, value.Style)
   LoadButtonsLabels()
   ShowValue()
   Me.Enabled = True
  End Set
 End Property
 <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
 Public Property A_FontSize As Single
  Get
   Return _font.Size
  End Get
  Set(value As Single)
   Me.Enabled = False
   If value < 10 Then value = 10
   If value > 50 Then value = 50
   _font = New Font(_font.Name, value, _font.Style)
   LoadButtonsLabels()
   ShowValue()
   Me.Enabled = True
  End Set
 End Property
 <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
 Public Property A_BackColor As Color
  Get
   Return Me.BackColor
  End Get
  Set(value As Color)
   Me.BackColor = NotTransparent(value)
  End Set
 End Property
 <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
 Public Property A_ButtonColor As Color
  Get
   Return _butColor
  End Get
  Set(value As Color)
   Me.Enabled = False
   _butColor = NotTransparent(value)
   LoadButtonsLabels()
   ShowValue()
   Me.Enabled = True
  End Set
 End Property
 <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
 Public Property A_TextForeColor As Color
  Get
   Return _textForeColor
  End Get
  Set(value As Color)
   Me.Enabled = False
   _textForeColor = NotTransparent(value)
   LoadButtonsLabels()
   ShowValue()
   Me.Enabled = True
  End Set
 End Property
 <DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)>
 Public Property A_TextBackColor As Color
  Get
   Return _textBackColor
  End Get
  Set(value As Color)
   Me.Enabled = False
   _textBackColor = NotTransparent(value)
   LoadButtonsLabels()
   ShowValue()
   Me.Enabled = True
  End Set
 End Property
End Class
  
Properties
Property Type Description
A_Value Integer Get/Set number displayed in the control
Value must be in range A_Minvalue to A_maxValue
A_MinValue Integer Get/Set smallest number control will accept
Display will add a +/- sign when A_MinValue is negative
A_MaxValue Integer Get/Set largest number control will accept
If A_MaxValue is negative, the buttons on +/- sign will be hidden
A_Font Font Font used to display the value
A_FontSize Single A very old compiler may expect Integer font sizes
A_BackColor Color Get/Set colour of control background
Transparent colours will be made opaque. (Avoids VB.Net limitation)
A_ButtonColor Color Get/Set colour of the buttons displayed in control
Transparent colours will be made opaque. (Avoids VB.Net limitation)
A_TextForeColor Color Get/Set colour of the digits displayed in control
Transparent colours will be made opaque. (Avoids VB.Net limitation)
A_TextBackColor Color Get/Set colour of the digit backgrounds displayed in control
Transparent colours will be made opaque. (Avoids VB.Net limitation)

DigitalDan.co.uk