VB.NET Knob Control






3.17/5 (7 votes)
Dec 13, 2004
3 min read

71642

1359
A usable knob control.
Introduction
Hello this is my first article. I always wanted to make a knob control and finally I did it, so here I am going to share what I did.
This is my tutorial for making a custom knob control. I made the knob image in a 3D modeling program, then edited it in PhotoShop, removed everything but the knob itself and saved it as a .png image. I even went a little farther and made another image of a pillow bevel which sits under the knob image to make the knob look sunk in.
Now I had my graphics done. Now for the coding part, since I wanted transparency and I made a user control, I had to insert these lines:
SetStyle(ControlStyles.SupportsTransparentBackColor, True)
Me.BackColor = Color.Transparent
If you do not know where to find the constructor then look under View - Object Browser. In the browser you will see the name of your project, double click it. Then it will expand and show you the same name again - double click it. Now it should expand and say usercontrol1
, double click it. You will see a Sub
called new
, and under the InitializeComponent()
is where you place those lines, since a user control by default cannot have transparency. Now we have the transparency issue taken care of.
Now for the images that we have got, in the Solution Explorer right click the name of your project and add existing items. Add the images for the knob. Then in the Solution Explorer right click one of the images and go to its properties. Change build action to embedded resource. Do the same for the other images. I like making my images embedded, so they are built into the .dll of the control.
Here is the function to read embedded resources. Make sure to import System.IO
and System.Reflection
:
Protected Function GetEmbeddedResourceStream(ByVal ResourceName _
As String) As Stream
Return System.Reflection.Assembly.GetExecutingAssembly()._
GetManifestResourceStream(ResourceName)
End Function
Here is where the drawing takes place, it scales too:
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
e.Graphics.ScaleTransform(scales, scales)
knobbase = New Bitmap(GetEmbeddedResourceStream("knob.knobbase.png"))
knob = New Bitmap(GetEmbeddedResourceStream("knob.knobtop.png"))
Me.Height = knobbase.Height * scales
Me.Width = knobbase.Width * scales
e.Graphics.DrawImage(knobbase, 0, 0)
e.Graphics.ResetTransform()
e.Graphics.ScaleTransform(scales, scales)
e.Graphics.TranslateTransform(knob.width/2, knob.width/2)
e.Graphics.RotateTransform(angle)
e.Graphics.DrawImage(knob, -knob.Width \ 2, -knob.Height \ 2)
End Sub
Now we need some way of rotating the knob, when the user clicks and holds the mouse button over the knob.
Private Sub UserControl11_MouseDown(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles Me.MouseDown
Dim centerofknobx As Integer = Me.Width / 2
Dim centerofknoby As Integer = Me.Height / 2
If knob1ismoving = False Then
knobstartangle = Me.cur_ang
mouseangle = Int(Math.Atan2((e.Y - centerofknoby), _
(e.X - centerofknobx)) * (180 / Math.PI)) + 180
knob1ismoving = True
End If
If melocked = True Then knob1ismoving = False
End Sub
What was done here is that the MouseDown procedure will calculate the angle of the mouse to the center of the knob, and make the variable knob1ismoving = True
unless the knob is locked.
Now while the mouse button is down and the mouse moves, we need a subroutine to track the angle's difference and apply it to the knob.
Private Sub UserControl11_MouseMove(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles Me.MouseMove
If knob1ismoving = True Then
Dim centerofknobx As Integer = Me.Width / 2
Dim centerofknoby As Integer = Me.Height / 2
Dim curmouseangle As Integer = Int(Math.Atan2((e.Y - centerofknoby),
(e.X - centerofknobx)) * (180 / Math.PI)) + 180
Dim difference As Integer = curmouseangle - mouseangle
Dim knobangle As Integer = knobstartangle + difference
angle = knobangle + (revolutions * 360)
If locked = True Then
If angle > maxangle Then angle = maxangle
If angle < minangle Then angle = minangle
End If
If oldmouseangle > 300 And curmouseangle < 60 Then
revolutions = revolutions + 1
oldmouseangle = curmouseangle
End If
If oldmouseangle < 60 And curmouseangle > 300 Then
revolutions = revolutions - 1
oldmouseangle = curmouseangle
End If
oldmouseangle = curmouseangle
End If
End Sub
This sub is mostly math. I made this function to know if the knob was turned more than once in either direction, because I need the knob to track multiple turns. It figures out the angle difference from the original angle then adds (revolutions + 360) to it for the final angle.
Finally, we need a subroutine to stop the knob from moving when the mouse button is released.
Private Sub UserControl11_MouseUp(ByVal sender As Object, _
ByVal e As System.Windows.Forms.MouseEventArgs) _
Handles Me.MouseUp
knob1ismoving = False
End Sub
Conclusion
A knob control consists of your knob image. You track mouse movements and figure out the angle difference as the mouse moves and apply it to your knob.
I made limits on my knob....Say I wanted to control the minutes on a clock. I could limit it to 590 degrees max, then divide the current angle by 10 to get the minute. This knob makes a great slider replacement. I'm sure more features could be added such as a 'snap' feature so that it moves a certain amount of degrees at a time.
Hope you enjoyed my article. The source will run on VB.NET 2005. It shouldn't be hard to port it to 2003.