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

Простые локализованные часы

Следующая программа использует аргумент форматирования F для вывода даты и времени в клиентской части формы.

SimpleClock.cs

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

  class SimpleClock: Form
  {
      public static void Main()
      {
          Application.Run(new SimpleClock());
      }
      public SimpleClock()
      {
          Text = "Simple Clock";
          BackColor = SystemColors.Window;
          ForeColor = SystemColors.WindowText;

          Timer timer    = new Timer();
          timer.Tick    += new EventHandler(TimerOnTick);
          timer.Interval = 1000;
          timer.Start();
      }
      private void TimerOnTick(object sender, EventArgs ea)
      {
          Invalidate();
      }
      protected override void OnPaint(PaintEventArgs pea)
      {
          StringFormat strfmt  = new StringFormat();
          strfmt.Alignment     = StringAlignment.Center;
          strfmt.LineAlignment = StringAlignment.Center;

          pea.Graphics.DrawString(DateTime.Now.ToString("F"),
                                  Font, new SolidBrush(ForeColor), 
                                  ClientRectangle, strfmt);
      }
  }

Программа инициализирует таймер на срабатывание каждую секунду, а обработчик события OnTick просто делает клиентскую часть формы недействительной. Вот как это выглядит в случае стандартного формата для США:


Рис. 10.2.

Но позвольте спросить: мы что, потратили столько времени на изучение работы со шрифтами только для того, чтобы создать такие убогие часы? Вряд ли.

Давайте ограничимся лишь отображением времени и максимально увеличим шрифт. Для этого потребуется лишь более творчески взглянуть на метод OnPaint.

DigitalClock.cs

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

  class DigitalClock: Form
  {
      public static void Main()
      {
          Application.Run(new DigitalClock());
      }
      public DigitalClock()
      {
          Text = "Digital Clock";
          BackColor = SystemColors.Window;
          ForeColor = SystemColors.WindowText;
          ResizeRedraw = true;
          MinimumSize = SystemInformation.MinimumWindowSize + new Size(0, 1);

          Timer timer    = new Timer();
          timer.Tick    += new EventHandler(TimerOnTick);
          timer.Interval = 1000;
          timer.Start();
      }
      private void TimerOnTick(object obj, EventArgs ea)
      {
          Invalidate();
      }
      protected override void OnPaint(PaintEventArgs pea)
      {
          Graphics grfx    = pea.Graphics;
          string   strTime = DateTime.Now.ToString("T");
          SizeF    sizef   = grfx.MeasureString(strTime, Font);
          float    fScale  = Math.Min(ClientSize.Width  / sizef.Width,
                                      ClientSize.Height / sizef.Height);
          Font     font    = new Font(Font.FontFamily,
                                      fScale * Font.SizeInPoints);

          sizef = grfx.MeasureString(strTime, font);

          grfx.DrawString(strTime, font, new SolidBrush(ForeColor), 
                          (ClientSize.Width  - sizef.Width ) / 2, 
                          (ClientSize.Height - sizef.Height) / 2);
      }
  }

В методе OnPaint строка, содержащая сведения о времени в нужном формате, сохраняется в переменной strTime и затем, используя прием о котором я говорил в главе 9, устанавливает максимально возможный для данных размеров клиентской области размер шрифта. Вот как это выглядит (для местных параметров США):


Рис. 10.3.

Увы, для того чтобы время можно было увидеть из любой точки комнаты, мы пожертвовали отображением даты. Возможно ли отображать и то и другое, сохранив при этом большой размер текста? Конечно! Весь фокус в том, что для этого не стоит использовать форматы, в которых дата и время выводятся в одной строке, а разделить их, отображая на экране друг под другом. Для этого между датой и временем поместим символ перевода строки.

DigitalClockWithDate.cs

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

  class DigitalClockWithDate: DigitalClock
  {
      public new static void Main()
      {
          Application.Run(new DigitalClockWithDate());
      }
      public DigitalClockWithDate()
      {
          Text += " with Date";
      }
      protected override void OnPaint(PaintEventArgs pea)
      {
          Graphics grfx    = pea.Graphics;
          DateTime dt      = DateTime.Now;
          string   strTime = dt.ToString("d") + "\n" + dt.ToString("T");
          SizeF    sizef   = grfx.MeasureString(strTime, Font);
          float    fScale  = Math.Min(ClientSize.Width  / sizef.Width,
                                      ClientSize.Height / sizef.Height);
          Font     font    = new Font(Font.FontFamily,
                                      fScale * Font.SizeInPoints);

          StringFormat strfmt = new StringFormat();
          strfmt.Alignment = strfmt.LineAlignment = StringAlignment.Center;

          grfx.DrawString(strTime, font, new SolidBrush(ForeColor), 
                          ClientRectangle, strfmt);
      }
  }

Метод MeasureString возвращает высоту двух строк текста и ширину самой длинной из них. Чтобы расположить строки в центре клиентской области, в методе DrawString я применил объект StringFormat. Для местных параметров США это выглядит так:


Рис. 10.4.

Вызов метода OnPaint каждую секунду может заставить вас беспокоиться об эффективности участка кода, отвечающего за прорисовку клиентской области. Не лучше ли, например, создавать требуемый шрифт в методе OnResize? Лучше. Но чтобы все это работало правильно, надо потрудиться. Размер шрифта зависит как от размера клиентской области так и от высоты и ширины строки текста. Конечно, обычно ширина текстовой строки не меняется ежесекундно. Но иногда она все-таки меняется. Ширина строки, указывающей время, зависит от того, одной или двумя цифрами отображается текущий час. А если время отображается в 24-часовом формате, строка с датой получается шире, и эта ширина зависит от месяца и числа.

Если для создания подходящего шрифта в программе предусмотрен отдельный метод, он должен содержать в своих полях сам шрифт и ширину текста, использующуюся для вычисления нужного размера шрифта. Метод вычисления размера шрифта, очевидно, должен вызываться из метода OnResize. Но он должен вызываться также и из метода OnPaint, если с момента последнего изменения размера шрифта ширина строки изменилась.


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

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