DegreesUpDown Control
Introduction
The code I will post here is for a custom Control called DegreesUpDown. The control is similar to a NumericUpDown only it shows degrees (from 0 to 359). The nice thing about it is that the degrees are shown in 3 digits (000, 050, 180, etc...).
The Code
You might have thought that the control inherits from NumericUpDown. Well, it does not. It inherits from DomainUpDown which is much more flexible. I cannot format the way numbers look in NumericUpDown, so the trick is to convert strings into numeric values.
------------------------------------------------
Imports System.ComponentModel
Imports CommonControls.CGraphicsCommon
Imports System.Drawing
Public Class DegreesUpDown
Inherits System.Windows.Forms.DomainUpDown
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
InitializeGraphics()
End Sub
'UserControl overrides dispose to clean up the component list.
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
'
'DegreesUpDown
'
Me.Wrap = True
End Sub
#End Region
Private Sub InitializeGraphics()
Me.Font = CommonFont
Me.BackColor = Color.FromArgb(238, 238, 238)
Me.BorderStyle = BorderStyle.FixedSingle
End Sub
Private Sub InitValues()
Me.Items.Clear()
Dim vals As ArrayList = New ArrayList(360)
For i As Integer = 359 To 0 Step -1
vals.Add(ConvertTo3Digits(i))
Next
Me.Items.AddRange(vals)
End Sub
Public Shared Function ConvertTo3Digits(ByVal i As Integer) As String
If (i >= 100) Then Return i.ToString()
If (i >= 10) Then Return "0" + i.ToString()
If (i >= 0) Then Return "00" + i.ToString()
Return "000"
End Function
<Browsable(False)> _
Public Shadows ReadOnly Property Items() As DomainUpDownItemCollection
Get
Return MyBase.Items
End Get
End Property
<Browsable(False), _
Bindable(True)> _
Public Property Value() As Long
Get
If (IsNothing(Me.SelectedItem)) Then Return 0
Return Long.Parse(Me.SelectedItem)
End Get
Set(ByVal Value As Long)
If IsNothing(Value) Then
Me.SelectedItem = "000"
RaiseEvent ValueChanged(Me, EventArgs.Empty)
Exit Property
End If
If (Value >= 360 Or Value < 0) Then
Me.Text = Value.ToString
FixHeading()
Else
Me.SelectedItem = ConvertTo3Digits(Value)
End If
RaiseEvent ValueChanged(Me, EventArgs.Empty)
End Set
End Property
<Category("Action"), _
Description("Raised when the value is changed")> _
Public Event ValueChanged As EventHandler
Private Sub DegreesUpDown_SelectedItemChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.SelectedItemChanged
RaiseEvent ValueChanged(Me, EventArgs.Empty)
End Sub
Protected Overrides Sub OnCreateControl()
Me.Items.Clear()
If Not DesignMode Then
Dim vals As ArrayList = New ArrayList(360)
For i As Integer = 359 To 0 Step -1
vals.Add(ConvertTo3Digits(i))
Next
Me.Items.AddRange(vals)
Me.SelectedIndex = 359
Else
Me.Text = "000"
End If
End Sub
Private Sub DegreesUpDown_Leave(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Leave
FixHeading()
End Sub
Private Sub FixHeading()
Try
Dim i As Integer = Integer.Parse(Me.Text)
If i < 0 Then
Me.SelectedIndex = ((-i) Mod 360) - 1
End If
If i > 359 Then
Me.SelectedIndex = 359 - (i Mod 360)
End If
If i < 359 And i > 0 Then _
Me.SelectedIndex = 359 - i
Catch ex As Exception
Me.SelectedIndex = 359
End Try
End Sub
Protected Overrides Sub UpdateEditText()
Try
Dim i As Integer = Integer.Parse(Me.Text)
If (i > 359 Or i < 0) Then
FixHeading()
Else
If Me.Text.Length <> 3 Then _
FixHeading()
End If
Catch ex As Exception
FixHeading()
Finally
MyBase.UpdateEditText()
End Try
End Sub
<Browsable(False)> _
Public Shadows Property Text() As String
Get
Return MyBase.Text
End Get
Set(ByVal Value As String)
MyBase.Text = Value
End Set
End Property
End Class
------------------------------------------------Explanations
On initialization, in method InitValues, I create 360 strings (000,001,...,359), and add them to the items collection of the DomainUpDown base. The method ConvertTo3Digits does the convertion from int to 3 digits string.
In order to make the control fill more like a NumericUpDown, I added a Value property, which is numeric. Convertion to string and vice versa is done. The event ValueChanged also emulate the corresponding event of NumericUpDown control.
The Items and Text properties is no longer needed for use, so they are shadowed and marked as Browsable false.
FixHeading method is a nice feature - when the user enters a number out of range 0..359, the control automatically convert the number to the appropriate degree (For example: -90 => 270).
Extensions
You can extend the control by adding an Increment property (pressing on the UpDown buttons as of now only increase or decrease by one).
Also, you can add Maximum and Minimum properties.
In addition, the range -180..180 can be useful.
0 Comments:
Post a Comment
<< Home