Вывод текста в клиентскую область формы
Упражнение 4.Организация прокрутки с помощью элемента Panel
Для создания полос прокрутки используем элемент Panel, который не имеет визуального представления, а служит для группирования визуальных элементов в качестве родителя. Мы добавим в наше приложение код создания элемента Panel по размерам клиентской области формы и включим в форме свойство автопрокрутки. Нужно создать обработчик события Paint для перерисовки элемента панель. Мы будем использовать в коде созданный нами ранее класс SysInfoStrings.
using System; using System.Windows.Forms; using System.Drawing; namespace Test { public class SysInfoPanel : Form { // Переменные-члены класса Single xCol; int linespacing; public SysInfoPanel() { // Начальные настройки формы this.Text = "Добавление полос прокрутки"; this.BackColor = SystemColors.Window; this.ForeColor = SystemColors.WindowText; this.AutoScroll = true;// Включить автопрокрутку в форме // Надбавка к области для скролирования формы this.AutoScrollMargin = new Size(10, 10); // Временно создать, чтобы измерить Graphics gr = this.CreateGraphics(); // Замерим длину пробела SizeF sizeF = gr.MeasureString(" ", Font); // Определим позицию второй колонки xCol = sizeF.Width + SysInfoStrings.MaxLabelWidth(gr, Font); linespacing = Font.Height; // Создать объект типа Panel Panel panel = new Panel(); // Указать панели в качестве родителя текущую форму // Каждый элемент управления должен иметь родителя!!! panel.Parent = this; // Создать делегата обработчика события Paint панели // Эту строку кода написать вручную!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! panel.Paint +=new PaintEventHandler(panel_Paint); // Задать левый верхний угол панели нулевым // (совместить с левым верхним углом клиентской области формы) panel.Location = Point.Empty; // Настроить правый нижний угол панели на размер документа panel.Size = new Size( (int)Math.Ceiling(xCol + SysInfoStrings.MaxValueWidth(gr, Font)), (int)Math.Ceiling(linespacing * SysInfoStrings.Count)); /* // Или то же самое по другому SizeF size_F = new SizeF( xCol + SysInfoStrings.MaxValueWidth(gr, Font), linespacing * SysInfoStrings.Count); panel.Size = Size.Ceiling(size_F); */ // Освободить занимаемые временным графическим объектов ресурсы gr.Dispose(); } } }Листинг 15.17. Код конструктора формы SysInfoPanel с панелью, организующей прокрутку
- Пропишите выделенный красным код регистрации обработчика вручную, чтобы правильно создать заготовку обработчика события Paint панели
- Заполните заготовку обработчика события Paint панели следующим кодом
private void panel_Paint(object sender, PaintEventArgs e) { Graphics gr = e.Graphics; // Перекрасим фон панели, чтобы видеть ее размеры // в клиентской области формы gr.Clear(Color.Yellow); SolidBrush brush = new SolidBrush(this.ForeColor); // Длина массива свойств int count = SysInfoStrings.Count; // Локальные ссылки на массивы через статические свойства String[] strArrayLabels = SysInfoStrings.Labels; String[] strArrayValues = SysInfoStrings.Values; // Выводим все строки на элемент Panel. Если часть из них не // поместится, то у элемента Panel появятся полосы прокрутки for(int i = 0; i < count; i++) { gr.DrawString(strArrayLabels[i], Font, brush, 0, i * linespacing); gr.DrawString(strArrayValues[i], Font, brush, xCol, i * linespacing); } }Листинг 15.18. Обработчик события Paint панели в классе SysInfoPanel
Мы создали объект панель и настроили ее размеры с помощью временного графического объекта, который использовался для измерения измерения позиции второй колонки. Мы назначили панели родителя - форму, чтобы панель принимала сообщения от Windows, которые передаются системой самой форме. Размеры панели соответствуют размерам отображаемого на ней документа и, если панель не помещается в своем родителе, то форма генерирует полосы прокрутки в соответствии со значением ее свойства AutoScroll. Мы создали делегата и обработчик для события Paint панели, чтобы панель могла восстанавливать себя всякий раз после своего разрушения на экране.
Метод Math.Ceiling() использовался для для дополнения вещественных значений до целого числа. Как альтернативу этому можно было создать структуру типа SizeF и использовать статический метод Size.Ceiling() для округления до целого
// Или то же самое по другому SizeF size_F = new SizeF( xCol + SysInfoStrings.MaxValueWidth(gr, Font), linespacing * SysInfoStrings.Count); panel.Size = Size.Ceiling(size_F);Листинг 15.19.
Постройте приложение и поизменяйте размеры формы. Как только размер клиентской области формы превысит размеры панели (которая определяется размерами документа), соответствующая полоса прокрутки исчезает.
И наоборот, как только панель не помещается в клиентской области формы по одному из измерений, то сразу появляется соответствующая полоса прокрутки или обе сразу.
Отметьте, что ползунки полос прокрутки изменяют свои размеры пропорционально отношению видимой части ко всему содержимому (в данном случае - отношением соответствующих размеров клиентской области формы к размерам панели).
Другой способ увидеть панель - установить свойство AutoScrollMargin формы в ее конструкторе. В этом случае область скролирования формы будет добавлена к размеру документа, т.е. полосу прокрутки будут исчезать только тогда, когда размер клиентской области превысит размер документа плюс значение свойства AutoScrollMargin в пикселах. Ну и, если переместить ползунки до конца вправо и до конца вниз в нашем примере, то можно увидеть эту белую границу заданной ширины (можно увидеть краешек клиентской области самой формы).
Использование классов System.Windows.Forms.HScrollBar и System.Windows.Forms.VScrollBar - более универсальный подход к прокрутке. Оба этих класса наследуют от класса ScrollBar, который имеет ряд свойств для настройки. Свойства Minimum и Maximum, в частности, позволяют задать числовые значения, соответствующие крайним положениям ползунка, внутри которых и может работать полоса прокрутки.
В случае применения автопрокрутки в этих свойствах нужды нет. Диапазон значений задается разность ширины и высоты клиентской области и ширины и высоты элементов управления (в нашем случае, единственного элемента Panel, на котором мы рисуем текст) плюс размеров окаймления, устанавливаемых свойством AutoScrollMargin формы.
Полосы прокрутки, созданные как отдельные элементы управления (объекты), генерируют событие Scroll, когда пользователь работает с полосой прокрутки. При автопрокрутке такое событие не возникает - по крайней мере получить к нему доступ из приложения нельзя.
Хотя последняя наша программа не обрабатывает событие Scroll, она обрабатывает событие Paint для панели. Когда программа выводит информацию на панель, прорисовывается только видимая область панели. Но при каждой прокрутке на экране появляются новые области панели и срабатывает событие Paint панели, чтобы их прорисовать. То же происходит при появления панели на переднем плане после ее закрытия другими окнами.
Механизм работы автопрокрутки
Среди многих классов, наследуемых классом Form, есть класс ScrollableControl и именно в нем реализована автопрокрутка.
Некоторые из свойств класса ScrollableControl с уровнем доступа "чтение/запись" приведены в таблице.
Давайте посмотрим, сможем ли мы заставить автопрокрутку работать без создания дочерних элементов управления, таких, как Panel.