Imports System.Math
Imports System.Drawing.Drawing2D
Public Class frmClock
Private cp As PointF ' Center point
'Private rct As RectangleF ' Bounding rect
Private tmr As Timer
Private smallerside As Integer ' Whatever is smaller - width or height of the form
Private pixelwidth As Single ' Used to determine the scalefactor for a pixel
Private hrspen, minpen, secpen, dialpen As Pen ' individual pens for the hands
' A hour hand makes 1 full turn per 12 hours or 12 * 3600 = 43200 seconds
Private Const H_INCREMENT As Double = 2 * PI / 43200
' A minute hand makes 1 full turn per 3600 seconds
Private Const M_INCREMENT As Double = 2 * PI / 3600
' A second hand makes 1 full turn per 60 seconds
Private Const S_INCREMENT As Double = 2 * PI / 60
Private Const H_LENGTH As Double = 0.5 ' Length of the hours hand
Private Const M_LENGTH As Double = 0.7 ' Length of the minutes hand
Private Const S_LENGTH As Double = 0.79 ' Length of the seconds hand
Private Sub frmClock_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
' Creating a timer
tmr = New Timer With {.Interval = 1000, .Enabled = True}
' Lambda for the handling of Timer.Tick
AddHandler tmr.Tick, Sub(timersender As Object, timere As EventArgs)
Me.Invalidate()
End Sub
End Sub
Private Sub frmClock_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
' Find the central point
cp = New PointF(CSng(Me.ClientSize.Width / 2), CSng(Me.ClientSize.Height / 2))
' Determine whatever is smaller - width or height
smallerside = CInt(IIf(Me.ClientSize.Width >= Me.ClientSize.Height, Me.ClientSize.Height, Me.ClientSize.Width))
' Find out what will be a pixel size in our logic coordinates:
pixelwidth = CSng(1 / smallerside)
' Preparing pens for each hand and the dial:
hrspen = New Pen(Brushes.Blue, 8 * pixelwidth)
minpen = New Pen(Brushes.Green, 4 * pixelwidth)
secpen = New Pen(Brushes.Red, 1 * pixelwidth)
dialpen = New Pen(Brushes.Black, 4 * pixelwidth)
' Re-drawing the form
Me.Invalidate()
End Sub
Private Sub frmClock_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
Me.Text = Now.ToString
Dim h_angle, m_angle, s_angle As Double ' For angles of each hand
' The transformation matrix
Dim mtrx As New Matrix
' Moving (0,0) to the center of the form
mtrx.Translate(cp.X, cp.Y)
' Scaling up the form (zoom in)
mtrx.Scale(smallerside * 0.5F, smallerside * 0.5F)
' Rotating -90 degrees
mtrx.Rotate(-90)
' Applying transformation
' Now we have a coordinate space
' with the center at (0,0) and
' the dial diameter of 0.9 of the smaller dimension of the form.
' And the angles are incremented CLOCKWISE!
e.Graphics.Transform = mtrx
Dim h, m, s As Double
' For 10:30 the hours will be 10.5 so that the hand was between 10 and 11
s = Now.Second
m = Now.Minute + s / 60
' 24 hour format requires removing 12 hours:
h = CDbl(IIf(Now.Hour > 12, Now.Hour - 12, Now.Hour)) + m / 60
' Determine the angle of each hand.
h_angle = h * 3600 * H_INCREMENT
m_angle = m * 60 * M_INCREMENT
s_angle = s * S_INCREMENT
' Calculating the coordinates of each hand:
Dim hpt As PointF = New PointF(CSng(Cos(h_angle) * H_LENGTH), CSng(Sin(h_angle) * H_LENGTH))
Dim mpt As PointF = New PointF(CSng(Cos(m_angle) * M_LENGTH), CSng(Sin(m_angle) * M_LENGTH))
Dim spt As PointF = New PointF(CSng(Cos(s_angle) * S_LENGTH), CSng(Sin(s_angle) * S_LENGTH))
' Center of the dial:
Dim stpt As Point = New Point(0, 0)
' Drawing the dial:
e.Graphics.DrawEllipse(dialpen, -0.9, -0.9, 1.8, 1.8)
' Drawing the hands:
e.Graphics.DrawLine(hrspen, stpt, hpt)
e.Graphics.DrawLine(minpen, stpt, mpt)
e.Graphics.DrawLine(secpen, stpt, spt)
End Sub
End Class