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

Прокрутка панели

.NET Framework содержит массу интересных элементов управления: от кнопок, списков и текстовых полей, до календарей, деревьев и таблиц. Но элемент панель в число интересных не входит. Панель не имеет визуального представления и не сильно влияет на интерфейс пользователя. Обычно панель применяют в архитектурных целях — чтобы сгруппировать элементы управления. Кроме того, панели бывают полезны, если нужен элемент управления без большой функциональной нагрузки.

В программе SysInfoPanel я создал панель, соответствующую по размерам отображаемой информации — т.е. достаточно большую для того, чтобы вместить 60 строк текста с информацией о системе. Я поместил этот элемент управления на клиентской части формы, позволив автопрокрутке разобраться со всем остальным.

SysInfoPanel.cs

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

  class SysInfoPanel: Form
  {
      readonly float cxCol;
      readonly int   cySpace;

      public static void Main()
      {
          Application.Run(new SysInfoPanel());
      }
      public SysInfoPanel()
      {
          Text = "System Information: Panel";
          BackColor = SystemColors.Window;
          ForeColor = SystemColors.WindowText;
          AutoScroll = true;

          Graphics grfx  = CreateGraphics();
          SizeF    sizef = grfx.MeasureString(" ", Font);
          cxCol   = sizef.Width + SysInfoStrings.MaxLabelWidth(grfx, Font);
          cySpace = Font.Height;

               // Создаем панель

          Panel panel    = new Panel();
          panel.Parent   = this;
          panel.Paint   += new PaintEventHandler(PanelOnPaint);
          panel.Location = Point.Empty;
          panel.Size     = new Size(
              (int) Math.Ceiling(cxCol + 
                                 SysInfoStrings.MaxValueWidth(grfx, Font)),
              (int) Math.Ceiling(cySpace * SysInfoStrings.Count));
          grfx.Dispose();
      }
      void PanelOnPaint(object obj, PaintEventArgs pea)
      {
          Graphics grfx       = pea.Graphics;
          Brush    brush      = new SolidBrush(ForeColor);
          int      iCount     = SysInfoStrings.Count;
          string[] astrLabels = SysInfoStrings.Labels;
          string[] astrValues = SysInfoStrings.Values;

          for (int i = 0; i < iCount; i++)
          {
               grfx.DrawString(astrLabels[i], Font, brush, 
                               0, i * cySpace);
               grfx.DrawString(astrValues[i], Font, brush, 
                               cxCol, i * cySpace);
          }
      }
  }

Для работы этой программы нужен файл SysInfoStrings.cs. Хорошим способом совместного использования файлов различными проектами в Visual C# .NET является выбор из меню Project команды Add Existing Item. (Ее также можно выбрать, щелкнув правой кнопкой имя проекта в окне Solution Explorer и раскрыв подменю Add.) Выберите имя существующего файла, который следует добавить к проекту, но вместо того, чтобы щелкнуть кнопку Open, щелкните расположенную рядом с ней стрелку и выберите команду Link File. Так вы избежите создания второй копии файла и проблем, которые могут возникнуть, если вы измените только одну из копий.

Взглянем на конструктор программы SysInfoPanel. Для включения автопрокрутки следует присвоить свойству AutoScroll формы значение true. Пока все довольно просто. Затем программа вычисляет значения cxCol и cySpace тем же способом, что и SysInfoList. Но перед уничтожением объекта Graphics она создает панель:

  Panel panel = new Panel();

Я присвоил ей имя panel и поместил ее на поверхности клиентской части формы. Поверхность, на которой расположен элемент управления, называется его предком (parent). Каждый элемент управления должен иметь предка. Выражение

  panel.Parent = this;

назначает предком панели форму программы. Ключевое слово this используется в методах или свойствах для ссылки на текущий экземпляр объекта; в данном случае слово this ссылается на созданный мною объект Form. Такое же значение передастся методу Application.Run в методе Main.

Я хочу иметь возможность выводить на панель графические данные. Для этого я назначаю обработчик событию Paint панели:

  panel.Paint += new PaintEventHandler(PanelOnPaint);

Подобный код я использовал в главе 2, когда назначал обработчики события Paint для форм, являющихся экземплярами объекта Form, а не классов-наследников. Метод PanelOnPaint принадлежит классу SysInfoPanel.

Также следует указать расположение панели относительно родительской поверхности. Свойство Location класса Panel указывает положение верхнего левого угла панели. В этой программе я хочу поместить верхний левый угол панели в точке (0, 0) клиентской области, что позволяет сделать инструкция:

  panel.Location = Point.Empty;

Однако особой нужды в этой инструкции нет, так как верхний левый угол любых элементов управления по умолчанию помещается в точку (0, 0).

Для правильной работы программы размер панели должен соответствовать размеру выводимой информации:

  panel.Size = new Size(
      (int) Math.Ceiling(cxCol + SysInfoStrings.MaxValueWidth(grfx, Font)),
      (int) Math.Ceiling(cySpace * SysInfoStrings.Count));

Переменная cxCol уже содержит значение ширины первой колонки с добавленным пробелом. Вызов метода MaxValueWidth класса SysInfoStrings возвращает максимальную ширину значений свойств SystemInformation. Высота панели устанавливается равной межстрочному интервалу, умноженному на количество строк. Я использовал метод Math.Ceiling для дополнения значений до целого числа. (Как альтернативу можно было создать объект SizeF, ширина и высота которого выражаются числами с плавающей точкой, и использовать статический метод Size.Ceiling для преобразования его в объект Size.)

Вот и все. Метод PanelOnPaint отображает информацию на поверхности панели с помощью такого же кода, что и в методе OnPaint класса SysInfoList.

Но в этой программе, как только панель становится шире клиентской области, автоматически появляется горизонтальная полоса прокрутки. Если высота панели превышает высоту клиентской области, справа появляется вертикальная полоса прокрутки. Процесс динамичен: при изменении размеров клиентской области программы полосы прокрутки появляются и исчезают по мере надобности. Ползунки полос прокрутки изменяют свои размеры, отражая пропорции видимой части ко всему содержимому. Так, высота ползунка вертикальной полосы прокрутки определяется отношением высоты клиентской области к высоте панели.


Рис. 4.4.

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

  panel.BackColor = Color.Honeydew;

Если затем вы сделаете клиентскую часть программы больше самой панели — так, чтобы исчезли полосы прокрутки, — вы сможете увидеть панель медового цвета на фоне формы (вероятно, белом). Другой способ увидеть панель — установить свойство AutoScrollMargin формы в конструкторе:

  AutoScrollMargin = new Size{10, 10);

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

Выше я говорил, что более универсальный подход к прокрутке — использовать специальные элементы управления. Полосы прокрутки, созданные как отдельные элементы управления, имеют свойства Minimum и Maximum, которые позволяют задать числовые значения, соответствующие крайним положениям ползунка. Так устанавливается диапазон значений, в пределах которого может работать данная полоса прокрутки. В случае автопрокрутки в этих свойствах нет нужды. Диапазон значений задается разностью ширины и высоты клиентской части и ширины и высоты области расположения элементов управления (или, в нашем случае, единственного элемента Panel). К этому значению прибавляется разница между величиной AutoScrollMargin и шириной и высотой клиентской части.

Когда пользователь работает с полосой прокрутки, созданной как отдельный элемент управления, последняя генерирует событие Scroll. При автопрокрутке такое событие не возникает — по крайней мере получить к нему доступ из приложения нельзя.

Хотя программа SysInfoPanel напрямую не обрабатывает события Scroll, она обрабатывает события Paint для панели. Когда программа выводит информацию на элемент управления, прорисовывается только видимая область этого элемента. При каждой прокрутке SysInfoPanel генерирует событие Paint, так как в видимую область попадает непрорисованное пространство.


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

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