*Fig 1 - Virtual Clock*

It's that time again! Time to check out a new project written C# and the .NET library. This article describes how to create a virtual clock in C#. The hands of the clock are drawn using GraphicPaths. The UML Design for the Virtual Clock is shown below:

*Fig 2 - UML Design of the Virtual Clock reverse engineered using WithClass 2000*

The design is a simple Composite of Hands and a ClockFace. The Hand class serves as a base class for the HourHand, MinuteHand, and SecondHand, each of which have their own GraphicsPath instance stored in the base class. Each time the timer ticks 1 second, the hands are redrawn according to the current time. The sequence of events are shown below:

*Fig 3 - One Second Timer Tick Sequence Diagram drawn in WithClass*

The Transform method takes the DateTime(which is actually the current time) and rotates the GraphicsPath of the clock hand by the corresponding Time component for the particular hand. Since the time component is different for each hand, the Transform Method is overridden for each hand. Below is the transform method for the MinuteHand:

public override void Transform(DateTime d)

{

// turn the datetime minute component into an angle

// remember: 60 seconds in 2 pi (1 circle)

// Also note that we need to add the fractional seconds component to get the most accuracy

double minuteTime = (double)d.Minute + (double)(d.Second/60.0);

double angle = ((double)minuteTime /60.0 ) * 360; // 2.0 * Math.PI;

// Rotate the graphics path

Rotate(angle);

}

The Rotation of the GraphicsPath is performed in the base class, because it's the same for all Hands on the Clock. Rotation of a GraphicsPath is done through a Matrix. (See previous articles mentioned above to see how this is done mathematically.) The code for the rotation of the hands is shown below:

public void Rotate(double angle)

{

// Create a copy of the Graphics Path from the 0 degree path

gp = (GraphicsPath)gpBase.Clone();

// create a new transformation matrix

Matrix mTransform = new Matrix();

// rotate the matrix around the midpoint of the clock at the angle passed in.

mTransform.RotateAt((float)angle, new PointF(midX, midY));

// Transform the Graphics Path (which is actually the clock hand)

gp.Transform(mTransform);

}

The other noteworthy code you might find interesting is the drawing of the clock face. The clock face is drawn by the ClockFace class. This class draws the circle for the clock as well as the numbers around the clock and the image inside the clock:

public void Draw(Graphics g)

{

// draw blank face of clock

DrawClockFace(g);

// Draw clock Image

DrawImage(g);

// draw numbers around the face

DrawNumbers(g);

// draw clock pin

DrawPin(g);

}

The Numbers on the clock are drawn using the sine and cosine functions to determine the numeral positions:

private void DrawNumbers(Graphics g)

{

// initialize the count of the numbers around the clock

int count = 1;

// cycle around the circle on the circle on the clock and draw each number in the correct position

for (double a = 0; a < 2 * Math.PI; a += (2.0* Math.PI/12))

{

// calculate the x position of the next number

double x = (ClockRectangle.Width - 70)/2 * Math.Cos(a - Math.PI/3) + (ClockRectangle.Width - 70)/2 + 25;

// calculate the y position of the next number

double y = (ClockRectangle.Width - 70)/2 * Math.Sin(a - Math.PI/3)+ (ClockRectangle.Width - 70)/2 + 20;

// Draw the next Number according to the calculated position around the inner circumference of the circle

g.DrawString(Convert.ToString(count), ClockFont, Brushes.Black, (float)x,(float)y, new StringFormat());

// Increment the next Number

count++;

}

}

**Improvements:**

This clock could use one of those little date squares on the right side showing the day of the week. Also an alarm wouldn't be bad <g>. Maybe on the next go around of the virtual clock. Time's up!