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
- The number of digits in the control is automatically governed by the largest(positive) or smallest(negative) value allowed.
- The plus/minus sign is automatically removed when not required (when all permitted values are positive)
-
The size of the control is automatically adjusted for optimum appearance. The properties controlling font size are
- Minimum and maximum value - affects number of digits and presence of +/- sign
- Font and Font Size
-
The size of the control should not be affected by
- Value changes whithin the current minimum-value and maximum-value
- Changing the colour of any part of the control.
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