Solved

circular progress bar (VB.NET 2010)

Posted on 2011-10-29
3,949 Views
Hi Experts,

I want to create a simple quiz app (WINFORM) (e.g. 10 questions). The score will be in a circle and I want some kind of progress bar wrapped around the circle... if player gets a point, the score +1 and progress percentage is displayed. I've no idea what best method to achieve this is... drawing a circle or using multiple images or manipulating a progress bar.

Thanks,
Roberto

images.jpg
0
Question by:RobertoFreemano

LVL 85

Expert Comment

Here's a basic circular progress bar:
*Set the Font, ForeColor, and PercentageColor Properties*
Idle-Mind-517959.flv

``````Imports System.Drawing.Drawing2D
Public Class CircleProgressBar
Inherits UserControl

Private center As Point
Private distance As Integer
Private Value As Integer
Private clr As Color

Public Property Percentage As Integer
Get
Return Me.Value
End Get
Set(ByVal value As Integer)
If value >= 0 AndAlso value <= 100 Then
Me.Value = value
Me.Refresh()
End If
End Set
End Property

Public Property PercentageColor As Color
Get
Return Me.clr
End Get
Set(ByVal value As Color)
Me.clr = value
End Set
End Property

Public Sub New()
Me.DoubleBuffered = True
End Sub

Private Function GetPoint(ByVal cx As Single, ByVal cy As Single, ByVal angleInDegrees As Single, ByVal distance As Single) As Point
' angleInDegrees
' Valid values are 0 --> 359 (six degrees = one minute on clock)
' draw a line from the center of the circle:
' 0 = up
' 90 = right
' 180 = down
' 270 = left

angleInDegrees = (angleInDegrees - 90) * Math.PI / 180

' Compute the point that is at the specified angle clockwise from straight up vertical and at the specifed distance
Return New Point(cx + distance * Math.Cos(angleInDegrees), cy + distance * Math.Sin(angleInDegrees))
End Function

Private Sub CircularProgressBar_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
Me.Refresh()
End Sub

Private Sub CircularProgressBar_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Dim G As Graphics = e.Graphics
center = New Point(Me.Width / 2, Me.Height / 2)

Dim rc As New Rectangle(center.X, center.Y, 1, 1)
rc.Inflate((Math.Min(Me.Width, Me.Height) / 2) * 0.85, (Math.Min(Me.Width, Me.Height) / 2) * 0.85)
G.FillEllipse(Brushes.Gray, rc)

rc = New Rectangle(center.X, center.Y, 1, 1)
rc.Inflate((Math.Min(Me.Width, Me.Height) / 2) * 0.65, (Math.Min(Me.Width, Me.Height) / 2) * 0.65)
G.FillEllipse(Brushes.White, rc)

rc = New Rectangle(center.X, center.Y, 1, 1)
rc.Inflate((Math.Min(Me.Width, Me.Height) / 2) * 0.45, (Math.Min(Me.Width, Me.Height) / 2) * 0.45)
G.FillEllipse(Brushes.Gray, rc)

Dim percentageRing As New GraphicsPath()
percentageRing.AddLines(BuildPercentageRing(center.X, center.Y, Me.Percentage, (Math.Min(Me.Width, Me.Height) / 2) * 0.7, (Math.Min(Me.Width, Me.Height) / 2) * 0.8).ToArray)
Using B2 As New SolidBrush(Me.PercentageColor)
G.FillPath(B2, percentageRing)
End Using
G.DrawPath(Pens.Black, percentageRing)

Dim txt As String = Me.Percentage & "%"
Dim szF As SizeF = G.MeasureString(txt, Me.Font)
Using B As New SolidBrush(Me.ForeColor)
G.DrawString(txt, Me.Font, B, New Point(center.X - szF.Width / 2, center.Y - szF.Height / 2))
End Using
End Sub

Private Function BuildPercentageRing(ByVal cx As Single, ByVal cy As Single, ByVal percentage As Integer, _
ByVal innerDistance As Single, ByVal outerDistance As Single) As List(Of Point)

Dim pList As New List(Of Point)
For i As Integer = 0 To percentage
pList.Add(GetPoint(cx, cy, (CDbl(i) / CDbl(100)) * 360, outerDistance))
If i Mod 5 = 0 Then
pList.Add(GetPoint(cx, cy, (CDbl(i) / CDbl(100)) * 360, innerDistance))
pList.Add(GetPoint(cx, cy, (CDbl(i) / CDbl(100)) * 360, outerDistance))
End If
Next
For i As Integer = percentage To 0 Step -1
pList.Add(GetPoint(cx, cy, (CDbl(i) / CDbl(100)) * 360, innerDistance))
Next
Return pList
End Function

End Class
``````
0

Author Comment

Sorry Mike,

I know it's me but i got erros :(

I created a new form2 to test the code.
``````Warning	2	'Public Sub New()' in designer-generated type 'Printer_Q.Form2' should call InitializeComponent method.	C:\Documents and Settings\bob_2\my documents\visual studio 2010\Projects\Printer_Q\Printer_Q\Form2.vb	30	16	Printer_Q

from line 31
``````
``````Error	1	Base class 'System.Windows.Forms.UserControl' specified for class 'Form2' cannot be different from the base class 'System.Windows.Forms.Form' of one of its other partial types.	C:\Documents and Settings\bob_2\my documents\visual studio 2010\Projects\Printer_Q\Printer_Q\Form2.vb	3	14	Printer_Q

from line 3
``````
0

LVL 85

Accepted Solution

No problem.

Click on Project --> Add User Control, type in CircleProgressBar, and then click on Add.
Hit F7 to view the code for the UserControl.
Paste the code above, except for line #3, over the code that is there.
Run the Project to make it compile.
Go back to the main Form.
You should now have a new control, CircleProgressBar, at the top of your ToolBox.

Change the ForeColor and Font properties to adjust the Text in the Middle.
Change the PercentageColor to change the color of the circular bar.

Change the Percentage() property to set the value at run-time:
``````Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For i As Integer = 1 To 100
CircleProgressBar1.Percentage = i
Application.DoEvents()
Next
End Sub
``````
0

LVL 85

Expert Comment

Did you ever get this to work for you Roberto?
0

Author Comment

Hi Mike,

Sorry, i didn't get chance yet.... I'll try this tonight :)
Thanks,
Rob
0

Author Comment

Hi Mike,

Sorry, i didn't get chance yet.... I'll try this tonight :)
Thanks,
Rob
0

Author Closing Comment

Thanks Mike,

Sorry it took me so long to get back to you ;)

Thanks again,
Roberto
0

Featured Post

Suggested Solutions

IP addresses can be stored in a database in any of several ways.  These ways may vary based on the volume of the data.  I was dealing with quite a large amount of data for user authentication purpose, and needed a way to minimize the storage.   …