1 | Imports System.Diagnostics |
---|
2 | Imports System.Drawing |
---|
3 | Imports System.Drawing.Imaging |
---|
4 | Imports System.Drawing.Drawing2D |
---|
5 | |
---|
6 | Public Class ProgressAnimation |
---|
7 | Private Const Spacing As Integer = 4 |
---|
8 | Private Const LeafCount As Integer = 13 |
---|
9 | Private Const RelativeOuterRadius As Double = 0.95 |
---|
10 | Private Const RelativeInnerRadius As Double = 0.2 |
---|
11 | Private Const RelativeInnerAngleSkew As Double = -30 * Math.PI / 180 ' 30 degrees skew |
---|
12 | Private Const RelativeLeafSpacing As Double = 0.2 |
---|
13 | Private Const UpdateInterval As Integer = 75 ' 75 milliseconds |
---|
14 | Private Const Period As Integer = 13000 ' 13 seconds |
---|
15 | Private ForegroundColor As Color = Color.MidnightBlue |
---|
16 | Private WithEvents UpdateTimer As Timer |
---|
17 | Private AnchorTickCount As Integer |
---|
18 | |
---|
19 | Private Sub ProgressAnimation_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load |
---|
20 | DoubleBuffered = True |
---|
21 | End Sub |
---|
22 | Private Sub ProgressAnimation_VisibleChanged(sender As Object, e As System.EventArgs) Handles Me.VisibleChanged |
---|
23 | If Visible Then |
---|
24 | UpdateTimer = New Timer |
---|
25 | UpdateTimer.Interval = UpdateInterval |
---|
26 | UpdateTimer.Start() |
---|
27 | AnchorTickCount = Environment.TickCount |
---|
28 | Invalidate() |
---|
29 | Else |
---|
30 | If UpdateTimer IsNot Nothing Then UpdateTimer.Stop() |
---|
31 | UpdateTimer = Nothing |
---|
32 | End If |
---|
33 | End Sub |
---|
34 | Private Sub ProgressAnimation_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint |
---|
35 | Dim Span As Integer = Math.Min(Width, Height) / 2 - Spacing |
---|
36 | If Span <= 0 Then Exit Sub |
---|
37 | Dim Origin As SizeF = New SizeF(Width / 2, Height / 2) |
---|
38 | Dim OutlinePen As Pen = New Pen(ForegroundColor, 1) |
---|
39 | e.Graphics.SmoothingMode = SmoothingMode.AntiAlias |
---|
40 | For LeafIndex As Integer = 0 To LeafCount - 1 |
---|
41 | Dim Position As Double = ((Environment.TickCount - AnchorTickCount) Mod Period) / Period + 0.55 |
---|
42 | Position += 1.0 * LeafIndex / LeafCount |
---|
43 | While Position > 1 |
---|
44 | Position -= 1 |
---|
45 | End While |
---|
46 | Debug.Assert(Position >= 0 AndAlso Position <= 1) |
---|
47 | Dim FillBrush As Brush = New SolidBrush(Color.FromArgb(31 + 224 * Math.Exp(-1.5 * Position), ForegroundColor)) |
---|
48 | Dim AngleA As Double = 2 * Math.PI * LeafIndex / LeafCount |
---|
49 | Dim AngleC As Double = 2 * Math.PI * (LeafIndex + 1) / LeafCount |
---|
50 | Dim AngleB As Double = AngleA * (RelativeLeafSpacing) + AngleC * (1 - RelativeLeafSpacing) |
---|
51 | Dim PointA1 As PointF = New PointF(Math.Sin(AngleA) * Span * RelativeOuterRadius, Math.Cos(AngleA) * Span * RelativeOuterRadius) |
---|
52 | Dim PointA2 As PointF = New PointF(Math.Sin(AngleA + RelativeInnerAngleSkew) * Span * RelativeInnerRadius, Math.Cos(AngleA + RelativeInnerAngleSkew) * Span * RelativeInnerRadius) |
---|
53 | Dim PointB1 As PointF = New PointF(Math.Sin(AngleB) * Span * RelativeOuterRadius, Math.Cos(AngleB) * Span * RelativeOuterRadius) |
---|
54 | Dim PointB2 As PointF = New PointF(Math.Sin(AngleB + RelativeInnerAngleSkew) * Span * RelativeInnerRadius, Math.Cos(AngleB + RelativeInnerAngleSkew) * Span * RelativeInnerRadius) |
---|
55 | Dim AngleD As Double = (AngleA + AngleB) / 2 |
---|
56 | Dim PointD1 As PointF = New PointF(Math.Sin(AngleD) * Span * RelativeOuterRadius, Math.Cos(AngleD) * Span * RelativeOuterRadius) |
---|
57 | Dim PointD2 As PointF = New PointF(Math.Sin(AngleD + RelativeInnerAngleSkew) * Span * RelativeInnerRadius, Math.Cos(AngleD + RelativeInnerAngleSkew) * Span * RelativeInnerRadius) |
---|
58 | Dim Path As GraphicsPath = New GraphicsPath |
---|
59 | Path.AddLine(PointA1 + Origin, PointA2 + Origin) |
---|
60 | Path.AddCurve(New PointF() {PointA2 + Origin, PointD2 + Origin, PointB2 + Origin}) |
---|
61 | Path.AddLine(PointB1 + Origin, PointB1 + Origin) |
---|
62 | Path.AddCurve(New PointF() {PointB1 + Origin, PointD1 + Origin, PointA1 + Origin}) |
---|
63 | e.Graphics.FillPath(FillBrush, Path) |
---|
64 | If Span >= 200 Then e.Graphics.DrawPath(OutlinePen, Path) |
---|
65 | Next |
---|
66 | End Sub |
---|
67 | Private Sub UpdateTimer_Tick(sender As Object, e As System.EventArgs) Handles UpdateTimer.Tick |
---|
68 | Invalidate() |
---|
69 | End Sub |
---|
70 | End Class |
---|