简单的时钟






4.13/5 (7投票s)
2002年10月13日

147398

1887
这个程序展示了如何制作一个简单的时钟。
引言
这个程序展示了如何使用 C# 制作一个时钟。程序非常简单,只涉及少量数学运算,我认为对于任何程序员来说都不应该太难。程序使用一个定时器,每 0.5 秒触发一次;myTimer_Tick()
获取系统当前时间(小时、分钟、秒),并将它们保存到相应的变量中。然后更新标题栏以显示时间数字,最后调用 updateClock()
,进而绘制时钟的指针。
updateClock()
创建一个新的位图,并将 clock.bmp 的 bmp 图像(保存在构造函数中的 'bitmap
' 变量中,并从程序的执行目录中获取)复制到另一个 Bitmap
变量。然后,它计算每个指针的角度,并将它们绘制在该变量上。最后,我们的位图变量被加载到表单上的 PictureBox
中。
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace Clock
{
/// <summary>
/// Summary description for Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.PictureBox pictureBox1;
private System.Windows.Forms.Timer myTimer;
private System.ComponentModel.IContainer components;
//Variables and objects created by us (not the designer)
//Holds current time components
private int hour, minute, second;
//The endpoint of clock's hand
private int xCordinate=150, yCordinate=150;
//Radius of the face of the clock
private int radius;
//Holds the clock's face
private Bitmap bitmap;
public Form1()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//Show in the titlebar
this.Text += " Getting time...";
//Set the radius as half the picturebox size
radius = this.pictureBox1.Width/2;
//Read the clock's face and save it to a bitmap object
bitmap = new Bitmap(Application.StartupPath + "\\clock.bmp");
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
本节是 VS.NET 表单设计器生成的所有代码。
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
System.Resources.ResourceManager resources =
new System.Resources.ResourceManager(typeof(Form1));
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.myTimer = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// pictureBox1
//
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(304, 304);
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
//
// myTimer
//
this.myTimer.Enabled = true;
this.myTimer.Interval = 500;
this.myTimer.Tick += new System.EventHandler(this.myTimer_Tick);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(300, 300);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.pictureBox1});
this.FormBorderStyle =
System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon =
((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.Name = "Form1";
this.ShowInTaskbar = false;
this.Text = "Clock";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
/// <summary>
/// The timer is fired every .6 second
/// (I call it a little before one second so
/// if the functions takes a while it won't
/// miss drawing a second.) It will then
/// get the current time and update the possition
/// of the hands through updateClock()
/// </summary>
private void myTimer_Tick(object sender, System.EventArgs e)
{
//Get the user's timezone
TimeZone myTime = TimeZone.CurrentTimeZone;
TimeSpan myTimeSpan =
myTime.GetUtcOffset(new DateTime(DateTime.Today.Year,
DateTime.Today.Month, DateTime.Today.Day));
DateTime today = DateTime.UtcNow;
//Localtime = UTC + UTC Offset
today = today.Add(myTimeSpan);
//Holds the current time components
hour = today.Hour;
minute = today.Minute;
second = today.Second;
//Update the titlebar's time
this.Text = "Clock " + hour + ":" + minute + ":" + second;
//Update the clock
updateClock();
}
/// <summary>
/// Draw the 3 hands on a new bitmap object and load it to picturBox.
/// </summary>
private void updateClock()
{
//The angle that the hand makes with PI/2 in radians
double angle=0;
//Relative lengths of hands
double hourSize=.65, minuteSize=.85, secondSize=.8;
//Make a new bitmap from the object
//saved from the disk, make a new pen
//and use antialiasing on the bitmap
//so our hands will look smooth
System.Drawing.Pen pen = new System.Drawing.Pen(Color.Black, 4);
Bitmap bitmaptemp = (Bitmap) this.bitmap.Clone();
Graphics gr = Graphics.FromImage(bitmaptemp);
gr.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
Point point1 = new Point(radius, radius), point2;
/*
* basically what we do in these steps is that
* we find the current hour,
* minute or seconds is what portion of the totall.
* Say we have 30 seconds;
* 30 seconds is 30/60 which is half of the circle
* if we our talking about seconds.
* So we multiply this by 2PI which is 360 degrees
* or one complete revoulution and we get the chunk
* of the circle that should have been covered
* by those seconds. Then if we get the Cosine
* of this angle and multiply it by
* the radius we get the X component of the endpoint
* of our seconds hand and if
* we multiply Sine of the angle by the radius
* we get the Y component of this
* end point. That's all we need in order to draw
* our hand, since our starting
* point is the center of the clock or basically
* point (radius, radius) where
* radius is just the clock's face width/2.
* If this is kind of confusing draw
* a sketch a unit circle with a ray going
* from the center and see how the
* sine and cosine of that angle from PI/2
* (not from 0, becuase our clock starts
* from PI/2 or 12 o'clock) relate
* to the X and Y component of the endpoint of the ray.
*
*/
//HOUR
if (hour <= 12)
angle = ((Math.PI / 2) - ((double)hour/12)* 2 * Math.PI);
else if (hour > 12)
angle = ((Math.PI / 2) - ((double)(hour-12)/12)* 2 * Math.PI);
xCordinate = radius + (int)(radius * Math.Cos(angle) * hourSize);
yCordinate = radius - (int)(radius * Math.Sin(angle) * hourSize);
//Draw
point2 = new Point(xCordinate, yCordinate);
gr.DrawLine(pen, point1, point2);
//MINUTE
angle = ((Math.PI / 2) - ((double)minute/60) * 2 * Math.PI);
pen.Width = 2;
xCordinate = radius + (int)(radius * Math.Cos(angle) * minuteSize);
yCordinate = radius - (int)(radius * Math.Sin(angle) * minuteSize);
//Draw
point2 = new Point(xCordinate, yCordinate);
gr.DrawLine(pen, point1, point2);
//SECOND
angle = ((Math.PI / 2) - (((double)second/60) * 2 * Math.PI));
pen.Width = 1;
xCordinate = radius + (int)(radius * Math.Cos(angle) * secondSize);
yCordinate = radius - (int)(radius * Math.Sin(angle) * secondSize);
//Draw
point2 = new Point(xCordinate, yCordinate);
gr.DrawLine(pen, point1, point2);
//Load the new bitmap to the picturebox
this.pictureBox1.Image = bitmaptemp;
pen.Dispose();
gr.Dispose();
}
}
}
上面,我有一段注释试图解释数学部分发生了什么。希望我表达清楚了!