netlib.narod.ru< Назад | Оглавление | Далее >

Стильные часы

За два десятилетия, прошедших с момента появления программ, имитирующих аналоговые часы, их внешний вид почти не изменился. Почти всегда программисты рисуют стрелки часов в виде незатейливых прямоугольников, но теперь пришла пора осваивать новые возможности. Для этого мы нарисуем стрелки при помощи кривых Безье.

Вспомните программу AnalogClock из главы 10, использующую элемент управления из класса ClockControl. К счастью, я предусмотрительно изолировал код для рисования стрелок в защищенных виртуальных методах этого класса. Вот класс BezierClockControl с новыми методами DrawHourHand и DrawMinuteHand, вызывающими DrawBeziers.

BezierClockControl.cs

  //---------------------------------------------------
  // BezierClockControl.cs (C) 2001 by Charles Petzold
  //---------------------------------------------------
  using System;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Windows.Forms;

  namespace Petzold.ProgrammingWindowsWithCSharp
  {
    class BezierClockControl: ClockControl
    {
        protected override void DrawHourHand(Graphics grfx, Pen pen)
        {
            GraphicsState gs = grfx.Save();
            grfx.RotateTransform(360f * Time.Hour / 12 +
                                  30f * Time.Minute / 60);

            grfx.DrawBeziers(pen, new Point[]
            {
                new Point(  0, -600), new Point(   0, -300), 
                new Point(200, -300), new Point(  50, -200), 
                new Point( 50, -200), new Point(  50,    0),
                new Point( 50,    0), new Point(  50,   75), 
                new Point(-50,   75), new Point( -50,    0), 
                new Point(-50,    0), new Point( -50, -200),
                new Point(-50, -200), new Point(-200, -300), 
                new Point(  0, -300), new Point(   0, -600)
            });
            grfx.Restore(gs);
        }
        protected override void DrawMinuteHand(Graphics grfx, Pen pen)
        {
            GraphicsState gs = grfx.Save();
            grfx.RotateTransform(360f * Time.Minute / 60 +
                                   6f * Time.Second / 60);

            grfx.DrawBeziers(pen, new Point[]
            {
                new Point(  0, -800), new Point(   0, -750), 
                new Point(  0, -700), new Point(  25, -600), 
                new Point( 25, -600), new Point(  25,    0),
                new Point( 25,    0), new Point(  25,   50), 
                new Point(-25,   50), new Point( -25,    0), 
                new Point(-25,    0), new Point( -25, -600),
                new Point(-25, -600), new Point(   0, -700), 
                new Point(  0, -750), new Point(   0, -800)
            });
            grfx.Restore(gs);
        }
    }
  }

При каждом вызове методу DrawBeziers передается массив из 16 структур Point для рисования 5 кривых Безье (помните, что при использовании метода DrawBeziers для рисования первой кривой Безье требуется задать 4 точки, а для каждой дополнительной кривой — по 3).

Исходная программа AnalogClock так мала, что я не вижу смысла использовать ее в качестве родительского класса. Вместо этого я написал совершенно новую программу BezierClock на основе класса BezierClockControl.

BezierClock.cs

  //--------------------------------------------
  // BezierClock.cs (C) 2001 by Charles Petzold
  //--------------------------------------------
  using Petzold.ProgrammingWindowsWithCSharp;
  using System;
  using System.Drawing;
  using System.Windows.Forms;

  class BezierClock: Form
  {
      BezierClockControl clkctl;

      public static void Main()
      {
          Application.Run(new BezierClock());
      }
      public BezierClock()
      {
          Text = "Bezier Clock";

          clkctl = new BezierClockControl();
          clkctl.Parent    = this;
          clkctl.Time      = DateTime.Now;
          clkctl.Dock      = DockStyle.Fill;
          clkctl.BackColor = Color.Black;
          clkctl.ForeColor = Color.White;

          Timer timer = new Timer();
          timer.Interval = 100;
          timer.Tick += new EventHandler(OnTimerTick);
          timer.Start();
      }
      void OnTimerTick(object obj, EventArgs ea)
      {
          clkctl.Time = DateTime.Now;
      }
  }

А вот результат ее работы:


Рис. 13.6.

Фигурный кончик каждой стрелки рисуется двумя симметричными кривыми Безье. Прямая часть стрелки нарисована другой парой кривых Безье, а закругленная часть в центре циферблата — еще одной кривой. Таким образом, каждая стрелка нарисована пятью кривыми.


netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz