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

Прокрутка при отсутствии элементов управления

Ключ к использованию автопрокрутки без создания дочерних элементов управления — в присваивании свойству AutoScrollMinSize значения отличного от (0, 0), устанавливаемого по умолчанию. Обычно область прокрутки основывается на положении и размере элементов управления в клиентской области. Однако AutoScrollMinSize задает минимальную область прокрутки независимо от наличия этих элементов. И, конечно, надо присвоить свойству AutoScroll значение true.

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

Программа SysInfoScroll по своей работе идентична SysInfoPanel, но она обеспечивает прокрутку содержимого при отсутствии дочерних элементов управления.

SysInfoScroll.cs

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

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

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

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

               // Устанавливаем свойства автопрокрутки

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

          grfx.Dispose();
      }
      protected override void OnPaint(PaintEventArgs pea)
      {
          Graphics grfx       = pea.Graphics;
          Brush    brush      = new SolidBrush(ForeColor);
          int      iCount     = SysInfoStrings.Count;
          string[] astrLabels = SysInfoStrings.Labels;
          string[] astrValues = SysInfoStrings.Values;
          Point    pt         = AutoScrollPosition;

          for (int i = 0; i < iCount; i++)
          {
              grfx.DrawString(astrLabels[i], Font, brush, 
                              pt.X, pt.Y + i * cySpace);

              grfx.DrawString(astrValues[i], Font, brush, 
                              pt.X + cxCol, pt.Y + i * cySpace); 
          }
      }
  }

SysInfoPanel в своей клиентской части содержала панель. Вы можете спросить, размещаются ли полосы прокрутки в клиентской части такой программы, как SysInfoScroll? Нет! На самом деле клиентская область уменьшается в размерах на ширину полос прокрутки. Бывает, что ширина клиентской области лишь немного превышает значение AutoScroltMinSize.Width. Однако при появлении вертикальной полосы прокрутки клиентская область сужается на ширину этой полосы; такое изменение может привести к тому, что ширина клиентской части станет меньше значения AutoScrollMinSize.Width и возникнет горизонтальная полоса прокрутки.

Устанавливая значение AutoScrollMinSize, вы не определяете что-либо подобное виртуальной области рисования. Независимо от того, насколько большое вы зададите значение AutoScrollMinSize, при обработке метода OnPaint вы работаете в границах физической клиентской области. На самом деле клиентская часть, вероятно, будет даже меньше обычных размеров из-за наличия полос прокрутки.

Любые действия с полосами прокрутки в SysInfoPanel приводили к отображению ранее скрытых областей панели и, следовательно, появлению события Paint. Та программа выводила всю информацию на панель, имеющую достаточные размеры для размещения этой информации. Прокрутка смещала панель относительно клиентской области, но координаты вывода информации на панель оставались неизменными. Например, вторая колонка третьего ряда текста всегда имела координаты (cxCol, 2 * cySpace).

SysInfoScroll реагирует на изменение состояния полос прокрутки в переопределяемом методе OnPaint формы. Эта программа выводит информацию прямо в клиентскую область, а не на элемент управления, который затем смещается. Клиентская область недостаточно велика для размещения всей нужной информации, а объект Graphics, используемый в методе OnPaint, ничего не знает об автопрокрутке.

Это значит, что в методе OnPaint программы SysInfoScroll (или любой другой, использующей автопрокрутку и при этом выводящей данные прямо в клиентскую область) при вызове любой функции, осуществляющей вывод на экран, надо корректировать координаты вывода, основываясь на свойстве AutoScrollPosition. Как видите, в этой программе метод OnPaint получает значение AutoScrollPosition, сохраняет его в переменной типа Point с именем pt и прибавляет это значение к координатам вывода при вызове DrawString. Помните, что значения координат в свойстве AutoScrollPosition отрицательные. Если, скажем, вы прокрутили информацию вниз на 30 пикселей, первый вызов DrawString для первой строки текста получит координаты вывода (0, –30), которые находятся выше клиентской области, и, следовательно, выводимая информация не будет видна.

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


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

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