Introduction

This code shows you how to build a fast and performing control using C# and .NET 2.0.

I wrote a similar control as an ActiveX once, using C++, ATL, and GDI, and wondered if it is possible to write performing code using .NET and GDI+. I needed it for another project. So I wrote this little control to show that it actually works.

How the Code Works

The code consists of a C# application and a custom control. The custom control really is the interesting part.

Deriving from Control

We derive from Control as this doesn't give us all these properties we don't actually need like a usercontrol would give us, for example.

publicpartialclass AGauge : Control

Dealing with Properties

Hiding, Shadowing Unwanted Properties

Well, there are still properties that show up in the designer that are not necessary. In C#, you can use the new keyword to get rid of them (shadows in VB).

publicnewBoolean AllowDrop, AutoSize, ForeColor, ImeMode

Overriding Useful Properties

For properties that you want to use but with a different behaviour, you can use the override keyword (if overrideable) to tell the program to call this overridden property instead of the implementation of the base class, which in our case is the implementation in Control.

The Browsable attribute tells the designer to show the property in the toolbox or not. The Category attribute tells the designer where to show the property if the categorized view is selected, and the Description attribute adds a description to the property that the designer can show in the toolbox.

Events and Delegates

An event can carry additional information that is sent to the "listening" program, e.g., the form's event handler for this event.

Custom Event Arguments

We want the event to carry the number of the range the needle is in (if it changes from being in one range to being in another). To add some data to the event, we derive from the standard event args and add a variable which is initialized in the constructor. This will hold the extra information sent along.

And the Event

[Description("This event is raised if the value falls into a defined range.")]publicevent ValueInRangeChangedDelegate ValueInRangeChanged;

The event is of the type we defined in the delegate statement. The Description attribute enables the designer to show a description for the event in the Toolbox.

Constructor

The constructor is called when the control is created, e.g., before it will be shown in the designer. Here, we set the style of the control to enable double buffering. This isn't really necessary since we will do our own double buffering, but it doesn't hurt to do so.

Overriding Member Functions

We need to override some of the member functions.

First, we override OnPaintBackground to ensure that the background is not painted each time the control is refreshed, this uses too much CPU even if double buffering is enabled. One drawback is that we need to handle the drawing of a background image ourselves, but this isn't too much of a problem.

protectedoverridevoid OnPaintBackground(PaintEventArgs pevent)
{
}

If the control is resized, we need to refresh it. So we override OnResize.

The global variable "drawGaugeBackground" is set to true to tell the control to completely redraw itself. Refresh forces the control to redraw, or if you like to call OnPaint, under the hood, a Windows message is sent, but this is a different story.

Finally, we need to override OnPaint to show some output to the user.

This is what our control really does, it shows the output to the user. It doesn't handle user input like a scrollbar would do. A scrollbar would override OnMouseMove, OnMouseDown, OnKeyPressed, and so on. OnPaint is the heart of our control.

protectedoverridevoid OnPaint(PaintEventArgs pe)

OnPaint, which is called every time the control is redrawn, e.g., if the value of the gauge changed, determines if it should completely redraw itself or simply paint the background part with the performant function DrawImage. If the background hasn't changed, it only needs to draw the needle, thus avoiding costly GDI+ functions to be called every time. The background changes, e.g., if a property like a color has changed, or the control is resized, for example.

Conclusion

So it really is possible to write fast and performing controls with GDI+ if we use double buffering and blitting (DrawImage).

If you like VB better than C#, you can search for "SpeedyHMI" on SourceForge, this project I wrote contains this gauge written in VB.

Share

About the Author

Once upon a time there was a C64.
He was a very friendly bilingual fellow looking like a bread box..
His user could always wake him up in no time and ask him to LOAD "*",8,1
C64's friends in school were called CBM, PET and Schneider.
They were boring to talk to after a while so his user got him a girlfriend called Amiga and a business partner called IBM.
Since vitamins are good, his user also got him an Apple to chew on.
As time went by the C64 and his friends got old and eventually were buried in oblivion.
In good memory his user did light a fire for them with a Sparc.
Since then cloning became very popular and the descendants of the C64's business partner rule the scene of his former user.
The descendants did breed many multilingual children of all sizes and shapes and the C64's former user is living happily with them ever after.

Seems like nobody noticed before
I put he bitmap in the zip file "AGaugeBmp.zip", it should be up soon.

In order to see the bitmap in the toolbox:
- You need to build a standalone control library containing the gauge control.
- Right click on the toolbox/ Choose items / Browse to the built control library..

a quick hack would be:
1)
set the values for the gauge multiplied by -1.
e.g. yourgauge.value=-yourvalue
This should take care of the needle moving into the "right", well opposite direction.

2)
find somewhere near line 1437 in the code of AGauge.cs:
valueText=(m_MinValue+countValue).ToString.......
replace with:
valueText=(-(m_MinValue+countValue)).ToString.......
This should take care of value texts

I actually inherited your code from someone else and have been playing around with it. I also wanted to flip the scale so it would go from 50, 45, 40, 35, 30, 25, 20 left to right (ubber crude drawing below) I tried changing valueText=(-(m_MinValue+countValue)).ToString...., but it only led to my numbers turning negative. I'm struggling to get them to literally flip to opposite sides of the gauge.

Tried turning the agauge.value to negative, but nothing happened :-/
Perhaps I'm not changing the right part?

Thank You for Your reply. That's a pity I'll try to inspire by Your C# code, GDI+ is the same library despite the language, so it should by nearly the same. Now it's time to complete this task, so I go to try it

' Copyright (C) 2007 A.J.Bauer
'
' This software is provided as-is, without any express or implied
' warranty. In no event will the authors be held liable for any damages
' arising from the use of this software.

' Permission is granted to anyone to use this software for any purpose,
' including commercial applications, and to alter it and redistribute it
' freely, subject to the following restrictions:

' 1. The origin of this software must not be misrepresented; you must not
' claim that you wrote the original software. if you use this software
' in a product, an acknowledgment in the product documentation would be
' appreciated but is not required.
' 2. Altered source versions must be plainly marked as such, and must not be
' misrepresented as being the original software.
' 3. This notice may not be removed or altered from any source distribution.

Public Class ValueInRangeChangedEventArgs
Inherits EventArgs
Public valueInRange As Int32

Public Sub New(ByVal valueInRange As Int32)
Me.valueInRange = valueInRange
End Sub
End Class

Public Delegate Sub ValueInRangeChangedDelegate(ByVal sender As [Object], ByVal e As ValueInRangeChangedEventArgs)
<Description("This event is raised if the value falls into a defined range.")> _
Public Event ValueInRangeChanged As ValueInRangeChangedDelegate
#End Region

End Set
End Property
<Browsable(False), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Shadows Property AutoSize() As [Boolean]
Get
Return False
End Get
Set(ByVal value As [Boolean])

End Set
End Property
<Browsable(False), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Shadows Property ForeColor() As [Boolean]
Get
Return False
End Get
Set(ByVal value As [Boolean])
End Set
End Property
<Browsable(False), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Shadows Property ImeMode() As [Boolean]
Get
Return False
End Get
Set(ByVal value As [Boolean])
End Set
End Property
<Browsable(False), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Overloads Overrides Property BackColor() As System.Drawing.Color
Get
Return MyBase.BackColor
End Get
Set(ByVal value As System.Drawing.Color)
MyBase.BackColor = value
drawGaugeBackground = True
Refresh()
End Set
End Property
<Browsable(False), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Overloads Overrides Property Font() As System.Drawing.Font
Get
Return MyBase.Font
End Get
Set(ByVal value As System.Drawing.Font)
MyBase.Font = value
drawGaugeBackground = True
Refresh()
End Set
End Property
<Browsable(False), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Overloads Overrides Property BackgroundImage() As System.Drawing.Image
Get
Return MyBase.BackgroundImage
End Get
Set(ByVal value As System.Drawing.Image)
MyBase.BackgroundImage = value
drawGaugeBackground = True
Refresh()
End Set
End Property
<Browsable(False), EditorBrowsable(EditorBrowsableState.Never), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _
Public Overloads Overrides Property BackgroundImageLayout() As System.Windows.Forms.ImageLayout
Get
Return MyBase.BackgroundImageLayout
End Get
Set(ByVal value As System.Windows.Forms.ImageLayout)
MyBase.BackgroundImageLayout = value
drawGaugeBackground = True
Refresh()
End Set
End Property
#End Region

For counter As Int32 = 0 To NUMOFRANGES - 2
If (m_RangeStartValue(counter) <= m_value) AndAlso (m_value <= m_RangeEndValue(counter)) AndAlso (m_RangeEnabled(counter)) Then
If Not m_valueIsInRange(counter) Then
RaiseEvent ValueInRangeChanged(Me, New ValueInRangeChangedEventArgs(counter))
End If
Else
m_valueIsInRange(counter) = False
End If
Next
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.RefreshProperties(RefreshProperties.All), System.ComponentModel.Description("The caption index. set this to a value of 0 up to 4 to change the corresponding caption's properties.")> _
Public Property Cap_Idx() As [Byte]
Get
Return m_CapIdx
End Get
Set(ByVal value As [Byte])
If (m_CapIdx <> value) AndAlso (0 <= value) AndAlso (value < 5) Then
m_CapIdx = value
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The color of the caption text.")> _
Private Property CapColor() As Color
Get
Return m_CapColor(m_CapIdx)
End Get
Set(ByVal value As Color)
If m_CapColor(m_CapIdx) <> value Then
m_CapColor(m_CapIdx) = value
CapColors = m_CapColor
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(False)> _
Public Property CapColors() As Color()
Get
Return m_CapColor
End Get
Set(ByVal value As Color())
m_CapColor = value
Refresh() ' JKW
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The text of the caption.")> _
Public Property CapText() As [String]
Get
Return m_CapText(m_CapIdx)
End Get
Set(ByVal value As [String])
If m_CapText(m_CapIdx) <> value Then
m_CapText(m_CapIdx) = value
CapsText = m_CapText
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(False)> _
Public Property CapsText() As [String]()
Get
Return m_CapText
End Get
Set(ByVal value As [String]())
For counter As Int32 = 0 To 4
m_CapText(counter) = value(counter)
Next
Refresh() ' JKW
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The position of the caption.")> _
Public Property CapPosition() As Point
Get
Return m_CapPosition(m_CapIdx)
End Get
Set(ByVal value As Point)
If m_CapPosition(m_CapIdx) <> value Then
m_CapPosition(m_CapIdx) = value
CapsPosition = m_CapPosition
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(False)> _
Public Property CapsPosition() As Point()
Get
Return m_CapPosition
End Get
Set(ByVal value As Point())
m_CapPosition = value
Refresh() ' JKW
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The center of the gauge (in the control's client area).")> _
Public Property Center() As Point
Get
Return m_Center
End Get
Set(ByVal value As Point)
If m_Center <> value Then
m_Center = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The minimum value to show on the scale.")> _
Public Property MinValue() As [Single]
Get
Return m_MinValue
End Get
Set(ByVal value As [Single])
If (m_MinValue <> value) AndAlso (value < m_MaxValue) Then
m_MinValue = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The maximum value to show on the scale.")> _
Public Property MaxValue() As [Single]
Get
Return m_MaxValue
End Get
Set(ByVal value As [Single])
If (m_MaxValue <> value) AndAlso (value > m_MinValue) Then
m_MaxValue = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The color of the base arc.")> _
Public Property BaseArcColor() As Color
Get
Return m_BaseArcColor
End Get
Set(ByVal value As Color)
If m_BaseArcColor <> value Then
m_BaseArcColor = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The radius of the base arc.")> _
Public Property BaseArcRadius() As Int32
Get
Return m_BaseArcRadius
End Get
Set(ByVal value As Int32)
If m_BaseArcRadius <> value Then
m_BaseArcRadius = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The start angle of the base arc.")> _
Public Property BaseArcStart() As Int32
Get
Return m_BaseArcStart
End Get
Set(ByVal value As Int32)
If m_BaseArcStart <> value Then
m_BaseArcStart = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The sweep angle of the base arc.")> _
Public Property BaseArcSweep() As Int32
Get
Return m_BaseArcSweep
End Get
Set(ByVal value As Int32)
If m_BaseArcSweep <> value Then
m_BaseArcSweep = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The width of the base arc.")> _
Public Property BaseArcWidth() As Int32
Get
Return m_BaseArcWidth
End Get
Set(ByVal value As Int32)
If m_BaseArcWidth <> value Then
m_BaseArcWidth = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The color of the inter scale lines which are the middle scale lines for an uneven number of minor scale lines.")> _
Public Property ScaleLinesInterColor() As Color
Get
Return m_ScaleLinesInterColor
End Get
Set(ByVal value As Color)
If m_ScaleLinesInterColor <> value Then
m_ScaleLinesInterColor = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The inner radius of the inter scale lines which are the middle scale lines for an uneven number of minor scale lines.")> _
Public Property ScaleLinesInterInnerRadius() As Int32
Get
Return m_ScaleLinesInterInnerRadius
End Get
Set(ByVal value As Int32)
If m_ScaleLinesInterInnerRadius <> value Then
m_ScaleLinesInterInnerRadius = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The outer radius of the inter scale lines which are the middle scale lines for an uneven number of minor scale lines.")> _
Public Property ScaleLinesInterOuterRadius() As Int32
Get
Return m_ScaleLinesInterOuterRadius
End Get
Set(ByVal value As Int32)
If m_ScaleLinesInterOuterRadius <> value Then
m_ScaleLinesInterOuterRadius = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The width of the inter scale lines which are the middle scale lines for an uneven number of minor scale lines.")> _
Public Property ScaleLinesInterWidth() As Int32
Get
Return m_ScaleLinesInterWidth
End Get
Set(ByVal value As Int32)
If m_ScaleLinesInterWidth <> value Then
m_ScaleLinesInterWidth = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The number of minor scale lines.")> _
Public Property ScaleLinesMinorNumOf() As Int32
Get
Return m_ScaleLinesMinorNumOf
End Get
Set(ByVal value As Int32)
If m_ScaleLinesMinorNumOf <> value Then
m_ScaleLinesMinorNumOf = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The color of the minor scale lines.")> _
Public Property ScaleLinesMinorColor() As Color
Get
Return m_ScaleLinesMinorColor
End Get
Set(ByVal value As Color)
If m_ScaleLinesMinorColor <> value Then
m_ScaleLinesMinorColor = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The inner radius of the minor scale lines.")> _
Public Property ScaleLinesMinorInnerRadius() As Int32
Get
Return m_ScaleLinesMinorInnerRadius
End Get
Set(ByVal value As Int32)
If m_ScaleLinesMinorInnerRadius <> value Then
m_ScaleLinesMinorInnerRadius = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The outer radius of the minor scale lines.")> _
Public Property ScaleLinesMinorOuterRadius() As Int32
Get
Return m_ScaleLinesMinorOuterRadius
End Get
Set(ByVal value As Int32)
If m_ScaleLinesMinorOuterRadius <> value Then
m_ScaleLinesMinorOuterRadius = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The width of the minor scale lines.")> _
Public Property ScaleLinesMinorWidth() As Int32
Get
Return m_ScaleLinesMinorWidth
End Get
Set(ByVal value As Int32)
If m_ScaleLinesMinorWidth <> value Then
m_ScaleLinesMinorWidth = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The step value of the major scale lines.")> _
Public Property ScaleLinesMajorStep() As [Single]
Get
Return m_ScaleLinesMajorStep
End Get
Set(ByVal value As [Single])
If (m_ScaleLinesMajorStep <> value) AndAlso (value > 0) Then
' JKW This line below caused problems!
' m_ScaleLinesMajorStep = Math.Max(Math.Min(value, m_MaxValue), m_MinValue)
m_ScaleLinesMajorStep = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The color of the major scale lines.")> _
Public Property ScaleLinesMajorColor() As Color
Get
Return m_ScaleLinesMajorColor
End Get
Set(ByVal value As Color)
If m_ScaleLinesMajorColor <> value Then
m_ScaleLinesMajorColor = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The inner radius of the major scale lines.")> _
Public Property ScaleLinesMajorInnerRadius() As Int32
Get
Return m_ScaleLinesMajorInnerRadius
End Get
Set(ByVal value As Int32)
If m_ScaleLinesMajorInnerRadius <> value Then
m_ScaleLinesMajorInnerRadius = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The outer radius of the major scale lines.")> _
Public Property ScaleLinesMajorOuterRadius() As Int32
Get
Return m_ScaleLinesMajorOuterRadius
End Get
Set(ByVal value As Int32)
If m_ScaleLinesMajorOuterRadius <> value Then
m_ScaleLinesMajorOuterRadius = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The width of the major scale lines.")> _
Public Property ScaleLinesMajorWidth() As Int32
Get
Return m_ScaleLinesMajorWidth
End Get
Set(ByVal value As Int32)
If m_ScaleLinesMajorWidth <> value Then
m_ScaleLinesMajorWidth = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.RefreshProperties(RefreshProperties.All), System.ComponentModel.Description("The range index. set this to a value of 0 up to 4 to change the corresponding range's properties.")> _
Public Property Range_Idx() As [Byte]
Get
Return m_RangeIdx
End Get
Set(ByVal value As [Byte])
If (m_RangeIdx <> value) AndAlso (0 <= value) AndAlso (value < NUMOFRANGES) Then
m_RangeIdx = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("Enables or disables the range selected by Range_Idx.")> _
Public Property RangeEnabled() As [Boolean]
Get
Return m_RangeEnabled(m_RangeIdx)
End Get
Set(ByVal value As [Boolean])
If m_RangeEnabled(m_RangeIdx) <> value Then
m_RangeEnabled(m_RangeIdx) = value
RangesEnabled = m_RangeEnabled
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(False)> _
Public Property RangesEnabled() As [Boolean]()
Get
Return m_RangeEnabled
End Get
Set(ByVal value As [Boolean]())
m_RangeEnabled = value
Refresh() ' JKW
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The color of the range.")> _
Public Property RangeColor() As Color
Get
Return m_RangeColor(m_RangeIdx)
End Get
Set(ByVal value As Color)
If m_RangeColor(m_RangeIdx) <> value Then
m_RangeColor(m_RangeIdx) = value
RangesColor = m_RangeColor
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(False)> _
Public Property RangesColor() As Color()
Get
Return m_RangeColor
End Get
Set(ByVal value As Color())
m_RangeColor = value
Refresh() ' JKW
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The start value of the range, must be less than RangeEndValue.")> _
Public Property RangeStartValue() As [Single]
Get
Return m_RangeStartValue(m_RangeIdx)
End Get
Set(ByVal value As [Single])
If (m_RangeStartValue(m_RangeIdx) <> value) AndAlso (value < m_RangeEndValue(m_RangeIdx)) Then
m_RangeStartValue(m_RangeIdx) = value
RangesStartValue = m_RangeStartValue
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(False)> _
Public Property RangesStartValue() As [Single]()
Get
Return m_RangeStartValue
End Get
Set(ByVal value As [Single]())
m_RangeStartValue = value
Refresh() ' JKW
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The end value of the range. Must be greater than RangeStartValue.")> _
Public Property RangeEndValue() As [Single]
Get
Return m_RangeEndValue(m_RangeIdx)
End Get
Set(ByVal value As [Single])
If (m_RangeEndValue(m_RangeIdx) <> value) AndAlso (m_RangeStartValue(m_RangeIdx) < value) Then
m_RangeEndValue(m_RangeIdx) = value
RangesEndValue = m_RangeEndValue
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(False)> _
Public Property RangesEndValue() As [Single]()
Get
Return m_RangeEndValue
End Get
Set(ByVal value As [Single]())
m_RangeEndValue = value
Refresh() ' JKW
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The inner radius of the range.")> _
Public Property RangeInnerRadius() As Int32
Get
Return m_RangeInnerRadius(m_RangeIdx)
End Get
Set(ByVal value As Int32)
If m_RangeInnerRadius(m_RangeIdx) <> value Then
m_RangeInnerRadius(m_RangeIdx) = value
RangesInnerRadius = m_RangeInnerRadius
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(False)> _
Public Property RangesInnerRadius() As Int32()
Get
Return m_RangeInnerRadius
End Get
Set(ByVal value As Int32())
m_RangeInnerRadius = value
Refresh() ' JKW
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The inner radius of the range.")> _
Public Property RangeOuterRadius() As Int32
Get
Return m_RangeOuterRadius(m_RangeIdx)
End Get
Set(ByVal value As Int32)
If m_RangeOuterRadius(m_RangeIdx) <> value Then
m_RangeOuterRadius(m_RangeIdx) = value
RangesOuterRadius = m_RangeOuterRadius
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(False)> _
Public Property RangesOuterRadius() As Int32()
Get
Return m_RangeOuterRadius
End Get
Set(ByVal value As Int32())
m_RangeOuterRadius = value
Refresh() ' JKW
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The radius of the scale numbers.")> _
Public Property ScaleNumbersRadius() As Int32
Get
Return m_ScaleNumbersRadius
End Get
Set(ByVal value As Int32)
If m_ScaleNumbersRadius <> value Then
m_ScaleNumbersRadius = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The color of the scale numbers.")> _
Public Property ScaleNumbersColor() As Color
Get
Return m_ScaleNumbersColor
End Get
Set(ByVal value As Color)
If m_ScaleNumbersColor <> value Then
m_ScaleNumbersColor = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The format of the scale numbers.")> _
Public Property ScaleNumbersFormat() As [String]
Get
Return m_ScaleNumbersFormat
End Get
Set(ByVal value As [String])
If m_ScaleNumbersFormat <> value Then
m_ScaleNumbersFormat = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The number of the scale line to start writing numbers next to.")> _
Public Property ScaleNumbersStartScaleLine() As Int32
Get
Return m_ScaleNumbersStartScaleLine
End Get
Set(ByVal value As Int32)
If m_ScaleNumbersStartScaleLine <> value Then
m_ScaleNumbersStartScaleLine = Math.Max(value, 1)
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The number of scale line steps for writing numbers.")> _
Public Property ScaleNumbersStepScaleLines() As Int32
Get
Return m_ScaleNumbersStepScaleLines
End Get
Set(ByVal value As Int32)
If m_ScaleNumbersStepScaleLines <> value Then
m_ScaleNumbersStepScaleLines = Math.Max(value, 1)
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The angle relative to the tangent of the base arc at a scale line that is used to rotate numbers. set to 0 for no rotation or e.g. set to 90.")> _
Public Property ScaleNumbersRotation() As Int32
Get
Return m_ScaleNumbersRotation
End Get
Set(ByVal value As Int32)
If m_ScaleNumbersRotation <> value Then
m_ScaleNumbersRotation = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The type of the needle, currently only type 0 and 1 are supported. Type 0 looks nicer but if you experience performance problems you might consider using type 1.")> _
Public Property NeedleType() As Int32
Get
Return m_NeedleType
End Get
Set(ByVal value As Int32)
If m_NeedleType <> value Then
m_NeedleType = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The radius of the needle.")> _
Public Property NeedleRadius() As Int32
Get
Return m_NeedleRadius
End Get
Set(ByVal value As Int32)
If m_NeedleRadius <> value Then
m_NeedleRadius = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The first color of the needle.")> _
Public Property NeedleColor1() As NeedleColorEnum
Get
Return m_NeedleColor1
End Get
Set(ByVal value As NeedleColorEnum)
If m_NeedleColor1 <> value Then
m_NeedleColor1 = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The second color of the needle.")> _
Public Property NeedleColor2() As Color
Get
Return m_NeedleColor2
End Get
Set(ByVal value As Color)
If m_NeedleColor2 <> value Then
m_NeedleColor2 = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The width of the needle.")> _
Public Property NeedleWidth() As Int32
Get
Return m_NeedleWidth
End Get
Set(ByVal value As Int32)
If m_NeedleWidth <> value Then
m_NeedleWidth = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("Enable/Disable the border around the gauge.")> _
Public Property BorderEnabled() As [Boolean]
Get
Return m_BorderEnabled
End Get
Set(ByVal value As [Boolean])
m_BorderEnabled = value
drawGaugeBackground = True
Refresh()
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The color of the gauge border.")> _
Public Property BorderColor() As Color
Get
Return m_BorderColor
End Get
Set(ByVal value As Color)
If m_BorderColor <> value Then
m_BorderColor = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property

<System.ComponentModel.Browsable(True), System.ComponentModel.Category("Gauge"), System.ComponentModel.Description("The color of the gauge border.")> _
Public Property BorderWidth() As Byte
Get
Return m_BorderWidth
End Get
Set(ByVal value As Byte)
If m_BorderWidth <> value AndAlso value <= 10 Then
m_BorderWidth = value
drawGaugeBackground = True
Refresh()
End If
End Set
End Property
#End Region

If m_ScaleNumbersRotation <> 0 Then
ggr.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SystemDefault
End If

For counter As Int32 = 0 To NUMOFCAPS - 1
If m_CapText(counter) <> "" Then
ggr.DrawString(m_CapText(counter), Font, New SolidBrush(m_CapColor(counter)), m_CapPosition(counter).X, m_CapPosition(counter).Y, StringFormat.GenericTypographic)
End If
Next

I have downloaded the VB .NET source from SourceForge... I found the dll in Debug and I am at loss how to use it to add such a dial on my form...
I tried running the project itself but it does nothing. I click on load, select the dll and nothing happens. No change to the drop-down menu on the left (as expected)...
Please help... Thanking in anticipation.