Исходники.Ру - Программирование
Исходники
Статьи
Книги и учебники
Скрипты
Новости RSS
Магазин программиста

Главная » Статьи по программированию » .NET - Windows Forms »

Обсудить на форуме Обсудить на форуме

Внешний вид Windows-форм
В этой статье Крис Селлз (Chris Sells) объясняет, как элементы управления размещаются на форме и масштабируются, а также как применять эти средства для удовлетворения потребностей разных пользователей в зависимости от системного размера шрифта и объема вводимых данных.

Аннотация

В этой статье Крис Селлз (Chris Sells) объясняет, как элементы управления размещаются на форме и масштабируются, а также как применять эти средства для удовлетворения потребностей разных пользователей в зависимости от системного размера шрифта и объема вводимых данных.

Скачать файл-пример winforms12102002.exe.

После всех этих сложных статей о потоках и безопасности, я решил вернуться к основам одной из наиболее захватывающей новых функциональности в Windows Forms - к тому, как элементы управления масштабируются и размещаются на форме. Эта функциональность применяется для удовлетворения потребностей разных пользователей с учетом размера системного шрифта и объема вводимых данных.

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

Допустим, вы создавали форму при размере системного шрифта, установленного через апплет Display (Экран) панели управления в Normal (Обычный) (96 DPI). Что будет, если пользователь сменит шрифт на Large (Крупный) (120 DPI) или выберет какое-нибудь нестандартное значение? Очевидно, вам хотелось бы, чтобы форма вроде приведенной на рис. 1 правильно показывалась при любых размерах шрифта.

Рис. 1. Пример формы при обычном размере шрифта

Если вы проведете тест, изменив размер с шрифта с обычного на крупный в Display (Microsoft Windows® XP потребует перезагрузки), то обнаружите, что форма с новым шрифтом выглядит, как показано на рис. 2, причем повторная компиляция приложения не понадобится.

Рис. 2. Пример формы с крупными шрифтами

Весь секрет в свойстве формы AutoScale. Если AutoScale равен true (по умолчанию), при первой загрузке формы считывается другое свойство - AutoScaleBaseSize. Оно устанавливается дизайнером и содержит среднюю ширину и высоту символов в шрифте формы. Шрифт по умолчанию - 8.25 pt MS Sans Serif при установке обычного размера шрифта в Windows XP - имеет среднюю ширину и высоту 5x13. Эта информация записывается в функции InitializeComponent так:

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

При использовании крупных шрифтов (шрифт по умолчанию - 7.8 pt MS Sans Serif) средняя ширина и высота оказываются равны 6x15 (именно поэтому такие шрифты называются "крупными"). При загрузке форма, вызвав Form.GetAutoScaleSize, обнаружит изменение масштаба, в котором она создавалась, по сравнению с текущим и изменит как свою высоту и ширину, так и высоту и ширину всех элементов управления (в том числе их позиции). Благодаря этому форма выглядит примерно одинаково вне зависимости от системных параметров шрифтов.

Привязка (Anchoring)

Конечно, одного масштабирования системных параметров шрифтов недостаточно для поддержки подстройки формы под запросы пользователей. Так, если пользователь в нашем примере захочет ввести в текстовое поле более длинную строку, он может попытаться растянуть форму, как показано на рис. 3.

Рис. 3. Все элементы управления привязаны к верхней левой точке

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

int delta = 0;

void Form1_Load(object sender, EventArgs e) {
  delta = ClientRectangle.Width - textBox1.Width;
}

void Form1_SizeChanged(object sender, EventArgs e) {
  textBox1.Width = ClientRectangle.Width - delta;
}

Во время события Load формы мы запоминаем разницу между шириной текстового поля и шириной клиентской прямоугольной области, а при изменении размера формы устанавливаем ширину поля так, чтобы разница оставалась постоянной. А значит, расстояние от правого края текстового поля до правого края формы остается неизменным. Этот процесс называется привязкой (anchoring). По умолчанию все элементы управления привязаны к левым и верхним краям своего контейнера (формы или элемента управления, содержащего другие элементы). Мы привыкли, что операционная система перемещает дочерние элементы управления так, что те остаются на постоянном расстоянии от левого и верхнего краев контейнера. Однако это все, на что способна операционная система. Так как она не в состоянии изменить размер наших элементов управления, привязывая их к другим краям, для изменения размера нужно писать код. Или, как делают чаще, использовать стили с фиксированными размерами формы. К счастью, в Windows Forms встроена поддержка привязки, что полностью избавляет от необходимости написания такого кода.

Чтобы сменить края, к которым привязывается элемент управления, измените свойство Anchor на любую побитовую комбинацию значений из перечислимого AnchorStyles:

enum AnchorStyles {
  None,
  Left, // по умолчанию
  Top, // по умолчанию
  Bottom,
  Right,
}

В нашем примере для изменения размера текстового поля в соответствии с изменением размера формы необходимо включить в свойство Anchor правый, а также левый и верхний края. Property Browser даже позволяет использовать весьма необычный редактор, приведенный на рис. 4.

Рис. 4. Настройка свойства Anchor в Property Browser

Стыковка

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

Стыковка (docking) - это способ задать конкретный край, к которому мы хотим "прижать" элемент управления. Так, на рис. 5 показана форма с тремя пристыкованными элементами управления: меню пристыковано к верхнему краю, строка состояния - к нижнему, а текстовое поле заполняет оставшееся свободное место.

Рис. 5. Пример стыковки

Стыковка реализуется присвоением свойству Dock всех элементов управления одного из значений перечислимого DockStyle (доступного через Property Browser, как показано на рис. 6):

enum DockStyle {
  None, // по умолчанию
  Left,
  Top,
  Right,
  Bottom,
  Fill,
}

Рис. 6. Настройка свойства Dock в Property Browser

Разделение

При применении стыковки часто нужно предоставить пользователю возможность изменять размеры некоторых элементов управления независимо от размеров формы. Например, Windows Explorer разбивает пространство между панелью инструментов и строкой состояния так, чтобы слева находился список с древовидным отображением, а справа - обычный список. Для изменения их размеров, служит разделитель (splitter), представляющий собой разделяющую два элемента управления полоску, при перетаскивании которой размеры двух элементов управления пропорционально изменяются. Простой пример элемента управления Splitter, расположенного между пристыкованным к левому краю элементом управления TreeView и элементом управления ListView, пристыкованным к правому краю, приведен на рис. 7.

Рис. 7. Пример разделения (заметьте, что курсор указывает на возможность перетаскивания)

Элементы управления "разделитель" (Splitter) доступны в Toolbox. Разделять элементы управления можно либо по вертикали - для этого следует установить свойство Dock равным DockStyle.Left (по умолчанию), либо по горизонтали, для чего запишите в это свойство значение DockStyle.Top. Пример разбиения по горизонтали приведен на рис. 8.

Рис. 8. Горизонтальное разделение

Группирование

Для более сложной разметки формы часто приходится разбивать элементы управления на несколько групп. Например, список сотрудников находится слева, а подробные сведения о текущем выбранном сотруднике выводятся справа, как показано на рис. 9.

Рис. 9. Пример группирования, стыковки и привязки

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

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

Элемент управления GroupBox - один из трех элементов-контейнеров, предлагаемых Windows-формами. К двум другим относятся Panel и TabControl. Первый из этих двух во всем похож на группирующий элемент за исключением того, что в нем нет метки и рамки. Панель удобна, если нужно получить что-то вроде субформы (одной формы внутри другой). TabControl - это контейнер, содержащий один или несколько элементов управления TabPage, каждый из которых в свою очередь тоже является контейнером с нарисованным сверху ярлычком вкладки, как показано на рис. 10.

Рис. 10. TabControl с двумя элементами управления TabPage

Нестандартная разметка формы

Сочетая привязку, стыковку, разделение и группироввание можно решить подавляющие большинство задач, связанных с разметкой форм. Но не все. Так, автоматическое растягивание элементов управления пропорционально клиентской области, в которой размещена таблица или сетка (как показано на рис. 11), реализовать с помощью этих способов не удастся.

Рис. 11. Пример нестандартной разметки

Чтобы создать форму, как на рис. 11, лучше всего выжать максимум возможного из уже описанных способов, а остальное сделать в обработчике события Layout формы или элементов-контейнеров. Например, следующий обработчик этого события размещает девять кнопок в соответствии с изменяющимися размерами формы:

void GridForm_Layout(object sender, LayoutEventArgs e) {
  // Разместить кнопки в сетке на форме
  Button[] buttons = new Button[] { button1, button2, ..., };
  int cx = ClientRectangle.Width/3;
  int cy = ClientRectangle.Height/3;
  for( int row = 0; row != 3; ++row ) {
    for( int col = 0; col != 3; ++col ) {
      Button button = buttons[col * 3 + row];
      button.SetBounds(cx * row, cy * col, cx, cy);
    }
  }
}

Заключение

Масштабирование позволяет размещать элементы управления на форме на этапе разработки при использовании одних настроек системных шрифтов и в то же время добиться корректного отображения формы при других настройках системных шрифтов в период выполнения. Например, даже если на этапе разработки установлен системный шрифт обычного размера, форма будет правильно выглядеть и при использовании крупных шрифтов. Привязка позволяет изменять размеры и перемещать элементы управления с фиксацией их по отношению к определенным краям формы. Стыковка фиксирует элемент управления на конкретном крае. Разделение дает возможность изменять размеры пристыкованных элементов управления, а группирование - разбивать элементы управления на небольшие группы, которыми легче управлять. Если же ничего из этого не помогает, зайдите с "черного хода" - воспользуйтесь событием Layout, позволяющим добиться функциональности, недостижимой с помощью вышеперечисленного арсенала средств.

Примечание Этот материал взят из готовящейся к публикации в издательстве Addison-Wesley книги Криса Селлза "Programming Windows Forms Applications with C#" (0321116208). Приведенный здесь материал - черновик того, что появится в опубликованной книге.

Крис Селлз (Chris Sells) - независимый консультант и преподаватель в DevelopMentor. Специализируется на распределенных приложениях в .NET и COM. Автор нескольких книг, в том числе "ATL Internals", которая в настоящее время перерабатывается для учета изменений, появившихся в ATL7. Кроме того, работает над книгами "Essential Windows Forms" (Addison-Wesley) и "Mastering Visual Studio .NET" (O'Reilly). В свободное время Крис поддерживает Web-сервисы DevCon и руководит Genghis - проектом с открытым исходным кодом. Более подробную информацию о нем и о его многочисленных проектах см. на сайте http://www.sellsbrothers.com.


Может пригодится:


Автор: Крис Селлз
Прочитано: 11293
Рейтинг:
Оценить: 1 2 3 4 5

Комментарии: (0)

Добавить комментарий
Ваше имя*:
Ваш email:
URL Вашего сайта:
Ваш комментарий*:
Код безопастности*:

Рассылка новостей
Рейтинги
© 2007, Программирование Исходники.Ру