65.9K
CodeProject 正在变化。 阅读更多。
Home

简单的时钟

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.13/5 (7投票s)

2002年10月13日

viewsIcon

147398

downloadIcon

1887

这个程序展示了如何制作一个简单的时钟。

Sample Image - clock.jpg

引言

这个程序展示了如何使用 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();                        
        }
    }
}

上面,我有一段注释试图解释数学部分发生了什么。希望我表达清楚了!

© . All rights reserved.