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

   
На этом шаге мы рассмотрим реализацию прокрутки в виде документа.

   
Вывод графической информации в логическое устройство ограничен только доступным диапазоном координат. В приложениях
для Windows 95 и Windows 98 графические координаты изменяются в пределах от -32768 до +32767.
В режиме МM_LOENGLISH этот диапазон соответствует физической области рисования, имеющей площадь
примерно 280 квадратных метров. Это намного больше любого мыслимого устройства вывода.

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

   
Можно самостоятельно организовать прокрутку в любом классе представления, применяя CWnd-функции
прокрутки и обрабатывая сообщения WM_VSCROLL и WM_HSCROLL. Однако намного проще
реализовать прокрутку средствами класса CScrollView, поскольку в нем предусмотрено:

  • управление размерами окна и области просмотра, а также режимами сопоставления координат;
  • автоматическая прокрутка в ответ на сообщения от полос прокрутки.

   
Познакомимся со средствами прокрутки класса CScrollView.

  • Просмотр стандартной реализации прокрутки в приложении МуАрр.
  • Запустите приложение МуАрр.
  • В меню Data выберите команду Edit, а затем наберите строку примерно из 60 символов, которая
    должна быть выведена 20 раз.
  • Уменьшите окна примерно так, как показано на рисунке 1.
    Рис.1. Проверка прокрутки в приложении МуАрр

   
Обратите внимание, что хотя прокрутка и выполняется автоматически, но в ее реализации имеются недостатки.
На рисунке 1 показано, что правая часть строк уже не просматривается, а горизонтальная полоса прокрутки еще не
появилась. Хотя, казалось бы, полосы прокрутки должны появляться на экране сразу же после того, как край рамки
обрезает выводимые в окно данные. И хотя при дальнейшем сужении окна горизонтальная полоса прокрутки
появляется, но она не позволяет увидеть всю строку.

   
Причина тому - не задан логический размер и режим сопоставления координат для прокрутки представления. Когда
AppWizard включает в создаваемое приложение класс, производный от CScrollView, он
добавляет в перегруженный метод CView::OnInitialUpdate() следующий код:

	CSize sizeTotal;
	// TODO: calculate the total size of this view
	sizeTotal.cx = sizeTotal.cy = 100;
	SetScrollSizes(MM_TEXT, sizeTotal);

   
Функция CScrollView::SetScrollSizes() задает логический размер и режим сопоставления координат для
прокрутки вида. Meтод OnInitialUpdate() по умолчанию устанавливает окна для вида размером 100 на 100 логических единиц.
В режиме ММ_ТEXT это соответствует экранной области просмотра размером 100 на 100 пикселей, или примерно
одному квадратному дюйму поверхности монитора с разрешением 800 на 600. У функции SetScrollSizes() есть
еще два параметра: размер строки и размер страницы. Первый - это величина горизонтальной и вертикальной прокрутки в
любом направлении при щелчке стрелки полосы прокрутки. Второй - это шаг прокрутки при щелчке любой области полосы прокрутки,
но не ее стрелки. Значения этих двух параметров рассчитываются по умолчанию исходя из общего размера окна.

   
Когда окно приложения MуAрр достаточно велико, виден весь текст. Если сжать окно так, чтобы его размер стал меньше значения
установленного в функции SetScrollSizes(), то появится полоса прокрутки. Масштаб и позиция движка в полосе
прокрутки также вычисляются в соответствии с установленным размером прокрутки. Поэтому в экспериментах со стандартным
поведением прокрутки в приложении МуАрр нельзя путем прокрутки увидеть данные, находящиеся вне логической
области окна размерами 100 на 100.

   
При установке в приложении с архитектурой "документ/вид" простой прокрутки для представления нужно выбрать размер
логической области графического представления данных документа. Затем надо определить режим сопоставления координат,
подходящий для масштабирования изображения на устройстве вывода, и задать значения, передаваемые SetScrollSizes() при
ее вызове в функции ОnInitialUpdate() класса представления. В следующем фрагменте кода показано, как установить
для вида размер 8,5 на 11 дюймов.

  sizeTotal.cx = 850; 
  sizeTotal.cy = 1100; 
  SetScrollSizes(MM_LOENGLISH, sizeTotal);

   
Этот метод годится при задании фиксированного размера данных приложения. Однако в таком приложении, как,
например, текстовый редактор, не существует ограничений на длину документа. При добавлении новых строк текста
придется изменять размер логической окна и пересчитывать масштаб полосы прокрутки, то есть всякий раз вызывать
SetScrollSizes() при изменении объема данных в документе.

   
В следующем примере в функции SetScrollSizes() откорректируем вид CMyAppView: полоса прокрутки
должна появляться пhb выходе отображаемых данных за рамку окна. Функция SetScrollSizes() будет вызываться из функции рисования,
чтобы размеры прокрутки вычислялись исходя из длины выводимой строки. Кроме того, в этой функции будет
устанавливаться режим MM_LOENGLISH, обеспечивающий одинаковый вывод как на экран, так и на принтер.

  • Установка размера прокрутки для приложения МуАрр.
  • На вкладке ClassView раскройте узел CMyAppView.
  • Дважды щелкните значок OnDraw(), чтобы отредактировать одноименный метод.
  • Ниже строки
        CSize TextSize = pDC->GetTextExtent(pDoc->m_string); 
    

    добавьте следующий код:

      CSize scrollArea = CSize(TextSize.cx,  TextSize.cy * pDoc->m_nLines);
      // Учитываем поля. 
      scrollArea += CSize(20, 20);
      SetScrollSizes(MM_LOENGLISH,   scrollArea);
    

       
    Размеры прокрутки устанавливаются исходя из размера отображаемых на экране данных (длины строки и числа строк).

       
    Если установлен режим ММ_ТЕХТ, то значения координаты у возрастают сверху вниз, в то время как
    в других фиксированных режимах, следующих математической традиции, значения у возрастают снизу вверх.
    Так как режим по умолчанию ММ_ТЕХТ изменен на MM_LOENGLISH, то нужно программно инвертировать
    координаты у, чтобы их значения уменьшались по мере продвижения вниз по странице.

  • Реализация инвертирования координаты у.
  • Найдите в функции OnDraw() следующие строки:
        int nLinePos = 10;
        for (int i = 0;   i < pDoc->m_nLines;   i++) 
       {
          pDC->TextOut(10,   nLinePos,   pDoc->m_string);
          nLinePos += TextSize.cy; 
       }
    
  • Задайте другое начальное значение для nPos, равное -10.
  • Замените оператор приращение nPos += на оператор уменьшения -=. Полностью функция должна выглядеть следующим образом:
    void CMyAppView::OnDraw(CDC* pDC)
    {
        CMyAppDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);
        CFont aFont;
        aFont.CreateFont(16,0,0,0,0,0,0,0,0,0,0,0,FF_ROMAN,0);
        CFont *pOldFont = pDC->SelectObject(&aFont);
        CSize TextSize = pDC->GetTextExtent(pDoc->m_string); 
        CSize scrollArea = CSize(TextSize.cx,  TextSize.cy * pDoc->m_nLines);
        // Учитываем поля. 
        scrollArea += CSize(20, 20);
        SetScrollSizes(MM_LOENGLISH,   scrollArea);
        int nLinePos = -10;
        for (int i = 0;   i < pDoc->m_nLines;   i++) 
        {
          pDC->TextOut(10,   nLinePos,   pDoc->m_string);
          nLinePos -= TextSize.cy; 
        }
        pDC->SelectObject(pOldFont); 
    }
    


    Рис.2. Текст функции OnDraw()

  • Соберите и запустите приложение МуАрр.
  • Уменьшите размер окна приложения и посмотрите, появляются ли полосы прокрутки сразу после того, как видимая
    область становится меньше выводимых в нее данных. Измените размер строки и число ее повторений и обратите внимание,
    как автоматически меняется масштаб полосы прокрутки в зависимости от объема выводимых данных.
  • Проверьте размер выводимого на печать текста, напечатав документ или выполнив команду Print Preview.

   
Текст измененного приложения можно взять здесь (61,4 Кб).

   
На следующем шаге мы рассмотрим рисование в контексте устройства.



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий