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

Подробнее о кнопках

Похоже, никакой катастрофы из-за того, что я не установил свойство Size объекта Button в программе SimpleButton, не случилось. На моем компьютере (и на вашем, возможно, тоже) кнопка получилась примерно такого размера, как нужно. Но если установить свойства дисплея на использование очень большого шрифта (больше Large Fonts), часть текста на кнопке может быть обрезана. А это не очень-то хорошо.

Когда вы размещаете на форме элементы управления, первейшим критерием должно быть удобство использования. Этот критерий включает в себя массу факторов. Так, элементов управления не должно быть слишком много, они должны быть выстроены в логическом порядке. Неплохо, когда форма эстетически гармонична. Но главное, текст на элементе управления не должен обрезаться! Может, пользователь и догадается, что «Cance» значит «Cancel» (Отмена), но программиста это характеризует не с лучшей стороны.

Как я покажу чуть позже, изменять размеры элементов управления можно по-разному. Если у вас есть опыт создания независимой от устройств графики, включающей текст, он вам пригодится. Но с элементами управления связаны определенные трудности. Например, если установить высоту кнопки равной высоте шрифта, текст все равно будет обрезан из-за наличия границы. Ширина границы кнопки — 4 пиксела, но никакого источника информации на этот счет нет, а кроме того, эта величина может быть другой при экзотических разрешениях экрана.

Так какой же высоты должна быть кнопка? Обычно рекомендуется 7/4 (или 175%) от высоты шрифта. В следующей программе высота кнопок вдвое больше высоты шрифта, и надо сказать, кнопки не кажутся слишком уж большими. Очень важно тестировать свою программу при разных разрешениях.

Если вы решите перевести приложение на другие языки, возникнут дополнительные проблемы. Перевод влияет на ширину текстовых строк: одни языки «длиннословнее» других.

В следующей программе две кнопки используются для демонстрации работы с размерами кнопок. Нажатие одной кнопки делает форму на 10% меньше, другой — на 10% больше (в пределах налагаемых Windows ограничений). Кнопки остаются в центре клиентской области.

TwoButtons.cs

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

  class TwoButtons: Form
  {
      readonly Button btnLarger, btnSmaller;
      readonly int    cxBtn, cyBtn, dxBtn;

      public static void Main()
      {
          Application.Run(new TwoButtons());
      }
      public TwoButtons()
      {
          Text = "Two Buttons";
          ResizeRedraw = true;

          cxBtn = 5 * Font.Height;
          cyBtn = 2 * Font.Height;
          dxBtn =     Font.Height;

          btnLarger = new Button();
          btnLarger.Parent = this;
          btnLarger.Text   = "&Larger";
          btnLarger.Size   = new Size(cxBtn, cyBtn);
          btnLarger.Click += new EventHandler(ButtonOnClick);

          btnSmaller = new Button();
          btnSmaller.Parent = this;
          btnSmaller.Text   = "&Smaller";
          btnSmaller.Size   = new Size(cxBtn, cyBtn);
          btnSmaller.Click += new EventHandler(ButtonOnClick);

          OnResize(EventArgs.Empty);
      }
      protected override void OnResize(EventArgs ea)
      {
          base.OnResize(ea);

          btnLarger.Location =
                         new Point(ClientSize.Width / 2 - cxBtn - dxBtn / 2,
                                  (ClientSize.Height - cyBtn) / 2);
          btnSmaller.Location =
                         new Point(ClientSize.Width / 2 + dxBtn / 2,
                                  (ClientSize.Height - cyBtn) / 2);
      }
      void ButtonOnClick(object obj, EventArgs ea)
      {
          Button btn = (Button) obj;

          if (btn == btnLarger)
          {
              Left   -= (int)(0.05 * Width);
              Top    -= (int)(0.05 * Height);
              Width  += (int)(0.10 * Width);
              Height += (int)(0.10 * Height);
          }
          else
          {
              Left   += (int)(Width  / 22f);
              Top    += (int)(Height / 22f);
              Width  -= (int)(Width  / 11f);
              Height -= (int)(Height / 11f);
          }
      }
  }

Конструктор вычисляет три значения и хранит их в полях: cxBtn и cyBtn определяют ширину и высоту каждой кнопки, a dxBtn — расстояние между двумя кнопками. Все три значения основываются на свойстве Height свойства Font формы. Так как элементы управления наследуют последнее свойство от предков, такой же размер имеет шрифт кнопок. Высота кнопок устанавливается вдвое больше высоты шрифта, а их ширина — впятеро больше ширины шрифта. (Я выбрал пять, так как для данной программы это неплохо работает, другие подходы мы обсудим потом.) Конструктор устанавливает только размер каждой кнопки, а не их расположение.

Так как расположение кнопки зависит от размера клиентской области, оно не устанавливается до тех пор, пока не вызывается метод OnResize. В первый paз он вызывается в последней инструкции конструктора.

Текст каждой кнопки начинается с амперсанда (&), что приводит к тому, что первая буква подчеркивается. Подчеркнутая буква работает как клавиша быстрого доступа. Во время работы программы можно на краткое время нажать клавишу Alt, и отобразятся подчеркивания.


Рис. 12.3.

Переключаться между кнопками можно, нажимая либо клавишу Tab, либо клавиши-стрелки. При переключении между кнопками перемещается пунктирная рамка внутри кнопки, указывая на то, что кнопка имеет фокус ввода. Когда кнопка имеет фокус ввода, весь клавиатурный ввод (кроме клавиш переключения между кнопками) направляется этой кнопке. Кнопка, имеющая фокус ввода, вызывает событие Click при нажатии пробела.

Кнопка по умолчанию обведена жирной линией — она получает нажатие клавиши Enter. Возможно, различие между кнопкой по умолчанию и кнопкой, имеющей фокус ввода, может показаться неочевидным. В этой программе это всегда одна и та же кнопка. Но по мере того, как вы будете знакомиться с другими элементами управления, отличие станет яснее. Кнопка, имеющая фокус ввода, всегда является кнопкой по умолчанию, но при этом, если другой элемент управления получит фокус ввода, кнопка по умолчанию, реагирующая на нажатие клавиши Enter, может продолжать существовать. В диалоговых окнах обычно кнопками по умолчанию являются кнопки с надписями OK, Open (Открыть) или Save (Сохранить). Эта кнопка срабатывает, когда фокус ввода имеет другой элемент управления и пользователь нажимает Enter. Кроме того, кнопка Cancel (Отмена) обычно является кнопкой отмены, срабатывающей при нажатии клавиши Esc. Я подробнее рассмотрю связанные с этим моменты в главе 16.

Можно заставить кнопку сработать, нажав клавишу, соответствующую подчеркнутой букве: L соответствует кнопке «Larger» (Больше), a S — «Smaller» (Меньше). Кнопка вызывает событие Click, однако фокус ввода не изменяется.

В начале метода ButtonOnClick параметр object приводится к типу Button. Теперь, сравнив этот объект с объектами btnLarger и btnSmaller, которые конструктор сохранил в полях, метод может принять решение о дальнейших действиях. В зависимости от того, какая кнопка была нажата, размер окна либо увеличивается, либо уменьшается на 10%. Кроме того, окно сдвигается на 5%, так что остается на одном и том же месте экрана.

Изменение размеров окна приводит к вызову метода OnResize, в котором кнопки перемещаются в новый центр клиентской области. Перемещение кнопок можно было бы осуществлять и в методе Click после вычисления размеров клиентской области, но в этом случае они бы не перемещались при ручном изменении размеров окна пользователем.

Является ли перемещение элементов управления в зависимости от размеров клиентской области обычным делом? Нет. Но чтобы обеспечить такую функциональность, нужно выйти за рамки того, что может предоставить Windows Forms Designer. Это еще одна причина, по которой приходится писать код вручную, — для достижения гибкости.


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

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