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

Автоматическое масштабирование

Программы из этой главы использовали свойство FontHeight формы, чтобы установить размер элементов управления с текстом. Для вычисления ширины элемента управления я брал половину высоты шрифта и считал ее примерно равной ширине символов в нижнем регистре. (Этого даже много для шрифта Courier.) Так как элементы управления наследуют шрифт от своих предков, этот способ отлично подходит для масштабирования элементов управления. Если нужно изменить шрифт формы (и элементов), это следует сделать в конструкторе формы до получения высоты шрифта.

.NET Framework предлагает иной метод масштабирования элементов управления, автоматическое масштабирование (auto-scale). Для этого служат свойства класса Form:


Свойства Form (выборочно)



Тип Свойство Доступ Описание

bool AutoScale Чтение/запись По умолчанию true
Size AutoScaleBaseSize Чтение/запись Высота и ширина шрифта формы


Единственный статический метод Form тоже связан с автоматическим масштабированием:


Статический метод Form



SizeF GetAutoScaleSize(Font font)


Свойство AutoScaleBaseSize и метод GetAutoScaleSize полезны сами по себе, даже если вы не применяете автоматическое масштабирование. В Windows Forms это единственный источник сведений о средней ширине символов конкретного шрифта. По умолчанию AutoScaleBaseSize возвращает ширину и высоту для шрифта, заданного в свойстве Font формы, a GetAutoScaleSize — ширину и высоту любого объекта Font. Возвращаемая ширина вычисляется как средняя на основе символов латинского алфавита в нижнем регистре. Высота же равна свойству Height объекта Font.

Допустим, вы установили в параметрах экрана Small Fonts. В таком случае AutoScaleBaseSize сообщает, что шрифт Windows Forms по умолчанию в 8 пт имеет ширину 5 и высоту 13 пикселов. Для Large Fonts, AutoScaleBaseSize сообщает о ширине 6 пикселов и высоте 15. Так что, если хотите точнее позиционировать элементы управления, используйте:

  cxText = AutoScaleBaseSize.Width;
  cyText = AutoScaleBaseSize.Height;

Только что я сказал, что AutoScaleBaseSize возвращает ширину и высоту, вычисленные на основе свойства Font формы. Это так. И если изменить свойство Font формы, AutoScaleBaseSize вернет ширину и высоту нового шрифта. Однако это справедливо лишь в том случае, если сама форма не устанавливает свойство AutoScaleBaseSize. Если же форма сама установила это свойство (я имею в виду, что вы написали код, устанавливающий это свойство), оно возвращает значение, заданное формой.

Вот в чем секрет автоматического масштабирования: если форма устанавливает свойство AutoScaleBaseSize, ширина и высота дочерних элементов управления масштабируется в зависимости от отношения высоты и ширины, определяемой свойством Font формы к высоте и ширине, определяемых свойством AutoScaleBaseSize. Если форма не устанавливает AutoScaleBaseSize, эти отношения равны 1, и масштабирования не происходит.

Вообще во время установки свойств Location и Size дочерних элементов управления форма может использовать любую систему координат и любые размеры. Затем с помощью AutoScaleBaseSize указывается система координат. Масштабирование происходит на основании текущих свойств Font и AutoScaleBaseSize после выполнения конструктора формы.

Поначалу автоматическое масштабирование выглядит сложным, так что рассмотрим несколько примеров.

Автоматическое масштабирование и Windows Forms Designer

Я уже упоминал, что однажды вам придется взглянуть на код, генерируемый Visual C# .NET Windows Forms Designer, и разобраться, что же там происходит. И вот вам пример — автоматическое масштабирование.

Допустим, для дисплея установлен размер шрифта Small Fonts. Когда вы конструируете форму с помощью Windows Forms Designer, он генерирует код, содержащий размер в пикселах. Например, свойство Size элемента управления Button можно установить так:

  this.button1.Size = new System.Drawing.Size(104, 26);

Да, Windows Forms Designer многословен. Но суть не в этом. Обычно жесткое кодирование положения и размеров элементов управления приводит к неприятностям. Можете быть уверены, что рано или поздно кто-нибудь запустит вашу программу в режиме Large Fonts или с еще большими шрифтами и текст на кнопках будет обрезан. Но Windows Forms Designer добавляет еще одну инструкцию в конструктор:

  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);

Этот размер представляет собой ширину и высоту шрифта в режиме Small Fonts. По сути дела Windows Forms Designer вставляет в код разрешение экрана, на котором основано местоположение и размеры элементов управления.

Если эта программа запускается на компьютере, на котором задан режим Small Fonts, отношение высоты и ширины шрифта к высоте и ширине свойства AutoScaleBaseSize равно 1, а местоположение и размеры элементов управления применяются напрямую.

Если же на компьютере действует режим Large Fonts, ширина и высота шрифта равны 6 и 15 соответственно. Когда конструктор формы завершает работу, Windows Forms масштабирует горизонтальные координаты и размеры, используя множитель 6/5 (это средняя ширина, вычисленная из свойства Font формы, деленная на AutoScaleBaseSize.Width). Вертикальные координаты и размеры масштабируются с использованием множителя 15/13, что представляет собой высоту шрифта формы, деленную на AutoScaleBaseSize.Height.

Именно так Windows Forms Designer избавляет от проблем, связанных с жестким заданием размеров и координат.

Вы и сами можете делать что-то в этом роде. Можно задавать все размеры и местоположение элементов управления так, чтобы они нормально выглядели на вашем компьютере, а затем добавить выражение, которое присваивает свойству AutoScaleBaseSize значение Size, соответствующее вашему компьютеру. Не забудьте проверить работу программы при разных размерах шрифта, изменяя либо размер шрифта в системе, либо задавая другое свойство Font в конструкторе.

Однако применение AutoScaleBaseSize может быть и более интересным.

Творческий подход к AutoScaleBaseSize

Обычно Windows-программисты, пишущие на С и C++, используя Win32 API или библиотеки Microsoft Foundation Class (MFC), определяют диалоговые окна в текстовом формате, называемом шаблоном диалогового окна, и применяют специальную независимую от устройства систему координат диалогового окна. Координаты х измеряются в 1/4 от средней ширины шрифта, координаты у — в 1/8 высоты шрифта. Так, если местоположение задано как (40, 32), элемент располагается на расстоянии 10 средних размеров символов по ширине от левого края диалогового окна и на расстоянии, равном высоте 4 символов от верхнего края.

В Windows Forms можно использовать ту же координатную систему. Все, что для этого нужно, — добавить в конструктор следующую инструкцию:

  AutoScaleBaseSize = new Size(4, 8);

С другой стороны, можно указывать размеры и местоположение в целых единицах высоты и ширины символов. В таком случае вам остается добавить лишь:

  AutoScaleBaseSize = new Size(1, 1);

Вообще-то такая система координат может показаться немного грубой. Обычно, чтобы экран выглядел более эстетично, расстояние между элементами управления по вертикали должно быть не меньше половины высоты шрифта.

Внутри автоматического масштабирования

После исполнения кода конструктора формы, она сама и ее дочерние элементы управления масштабируются на основании свойств Font и AutoScaleBaseSize формы. На самом деле масштабирование выполняется защищенным методом ScaleCore класса Control, вызываемом сначала для формы, а затем для всех дочерних элементов управления.

Можно самостоятельно выполнять то, что делает автоматическое масштабирование, используя методы Scale:


Методы Control (выборочно)



void Scale(float fScale)
void Scale(float xScale, yScale)


Например, установив свойство AutoScale в false, вы можете имитировать автоматическое масштабирование, вставив такие строки в конце конструктора формы:

  Scale(GetAutoScaleSize(Font).Width  / AutoScaleBaseSize.Width,
        GetAutoScaleSize(Font).Height / AutoScaleBaseSize.Height);

Это ширина и высота Font формы, деленные на высоту и ширину, указанные в свойстве AutoScaleBaseSize.

Если нужно перемасштабировать элементы управления — к примеру, потому что вы изменили свойство Font где либо еще, кроме конструктора, — не полагайтесь на то, что автоматическое масштабирование выполнит эту работу за вас. Вам придется напрямую вызвать Scale. Имейте в виду: форма и элементы управления не хранят историю предыдущих масштабирований. После того, как элементы управления были масштабированы в конструкторе, их размеры и местоположения представляют собой значения в пикселах. Нельзя просто вызвать Scale с параметрами, рассчитанными из свойств формы Font и AutoScaleBaseSize. Вам придется вычислить масштабирующий коэффициент на основе размера старого и нового шрифтов.

В следующей программе создается пять кнопок, позволяющих вам выбрать различные размеры шрифта. Конструктор программы использует размеры и местоположение на основе традиционной системы координат диалогового окна. Автоматическое масштабирование выполняет начальное масштабирование. При щелчке по кнопке обработчик события Click заново масштабирует все на основе текущего и нового шрифтов.

AutoScaleDemo.cs

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

  class AutoScaleDemo: Form
  {
      public static void Main()
      {
          Application.Run(new AutoScaleDemo());
      }
      public AutoScaleDemo()
      {
          Text = "Auto-Scale Demo";
          Font = new Font("Arial", 12);
          FormBorderStyle = FormBorderStyle.FixedSingle;

          int[] aiPointSize = { 8, 12, 16, 24, 32 };

          for (int i = 0; i < aiPointSize.Length; i++)
          {
              Button btn    = new Button();
              btn.Parent    = this;
              btn.Text      = "Use " + aiPointSize[i] + "-point font";
              btn.Tag       = aiPointSize[i];
              btn.Location  = new Point(4, 16 + 24 * i);
              btn.Size      = new Size(80, 16);
              btn.Click    += new EventHandler(ButtonOnClick);
          }
          ClientSize = new Size(88, 16 + 24 * aiPointSize.Length);
          AutoScaleBaseSize = new Size(4, 8);
      }
      protected override void OnPaint(PaintEventArgs pea)
      {
          pea.Graphics.DrawString(Text, Font, 
                                  new SolidBrush(ForeColor), 0, 0);
      }
      void ButtonOnClick(object obj, EventArgs ea)
      {
          Button btn = (Button) obj;

          SizeF sizefOld = GetAutoScaleSize(Font);
          Font = new Font(Font.FontFamily, (int) btn.Tag);
          SizeF sizefNew = GetAutoScaleSize(Font);

          Scale(sizefNew.Width  / sizefOld.Width,
                sizefNew.Height / sizefOld.Height);
      }
  }

Для хранения целочисленного значения размера в пунктах, связанного с каждой кнопкой, в программе используется свойство Tag элемента управления Button. В методе ButtonOnClick свойство Tag приводится к целому числу и создается шрифт. Вот окно программы при установленном размере шрифта формы 12 пт:


Рис. 12.14.

При щелчках по кнопкам размер формы изменяется согласно новому размеру шрифта.

Если создать элемент управления не в конструкторе формы, а где-то еще, придется вызвать метод Scale элемента управления с размерами текущего шрифта и свойством AutoScaleBaseSize.


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

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