private const int CLEARANCE = 10;
private const int MIN_DIAMETER = 50;
private const int DEGREES_PER_HOUR = 30;
private const int DEGREES_PER_MINUTE = 6;
private const int DEGREES_PER_SECOND = 6;
private readonly Pen hourPen = Pens.Black;
private readonly Pen minutePen = Pens.Blue;
private readonly Pen secondPen = Pens.Red;
private float GetHourAngle(DateTime currentTime)
{
return (currentTime.Hour % 12 + (currentTime.Minute + currentTime.Second / 60F) / 60F) * DEGREES_PER_HOUR;
}
private float GetMinuteAngle(DateTime currentTime)
{
return (currentTime.Minute + currentTime.Second / 60F) * DEGREES_PER_MINUTE;
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
var diameter = Math.Max(MIN_DIAMETER,
Math.Min(pictureBox1.Width,
pictureBox1.Height) - 2 * CLEARANCE);
// Ensure that the diameter is an odd number so there is a definite centre.
diameter = diameter % 2 == 0 ? diameter + 1 : diameter;
var g = e.Graphics;
// Draw the clock outline.
g.DrawEllipse(Pens.Black, CLEARANCE, CLEARANCE, diameter, diameter);
// Shift the origin to the centre of the circle to make it easy to draw radial lines.
g.TranslateTransform(CLEARANCE + diameter / 2 + 1, CLEARANCE + diameter / 2 + 1);
// Draw the hour and minute increments.
for (var a = DEGREES_PER_MINUTE; a <= 360; a += DEGREES_PER_MINUTE)
{
g.RotateTransform(DEGREES_PER_MINUTE);
if (a % DEGREES_PER_HOUR == 0)
{
// Hour markers are the length of the clearance.
g.DrawLine(hourPen, 0, CLEARANCE - diameter / 2, 0, -diameter / 2);
}
else
{
// Minute markers are the half the length of the clearance.
g.DrawLine(minutePen, 0, (CLEARANCE - diameter) / 2, 0, -diameter / 2);
}
}
var currentTime = DateTime.Now;
var hourAngle = GetHourAngle(currentTime);
var minuteAngle = GetMinuteAngle(currentTime);
var secondAngle = currentTime.Second * DEGREES_PER_SECOND;
var fullHandLength = diameter / 2 - CLEARANCE;
// The hands are drawn vertically upward in relation to the transformed coordinate system so the Y coordinate of the end-point is negative.
// Draw the minute hand first.
g.RotateTransform(minuteAngle);
g.DrawLine(minutePen, 0, 0, 0, -fullHandLength);
g.RotateTransform(-minuteAngle);
// Draw the hour hand over the minute hand.
g.RotateTransform(hourAngle);
g.DrawLine(hourPen, 0, 0, 0, -fullHandLength / 2);
g.RotateTransform(-hourAngle);
// Draw the second hand over all others.
g.RotateTransform(secondAngle);
g.DrawLine(secondPen, 0, 0, 0, -fullHandLength);
g.RotateTransform(-secondAngle);
}
private void pictureBox1_SizeChanged(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}
private void timer1_Tick(object sender, EventArgs e)
{
pictureBox1.Invalidate();
}