Книга: C# для профессионалов. Том II

OnPaint()

OnPaint()

Итак, мы увидели, как CapsEditor загружает файл. Теперь пришло время посмотреть, как выполняется рисование:

protected override void OnPaint(PaintEventArgs e) {
 Graphics dc = e.Graphics;
 int scrollPositionX = this.AutoScrollPosition.X;
 int scrollPositionY = this.AutoScrollPosition.Y;
 dc.TranslateTransform(scrollPositionX, scrollPositionY);
 if (!documentHasData) {
  dc.DrawString("<Empty Document>", emptyDocumentFont,
   emptyDocumentBrush, new Point(20, 20));
  base.OnPaint(e);
 return;
 }
 // определить, какие строки находятся в вырезанном прямоугольнике
 int minLineInClipRegion =
  WorldYCoordinateToLineIndex(е.ClipRectangle.Top - scrollPositionY);
 if (minLineInClipRegion == -1) minLineInClipRegion = 0;
 int maxLineInClipRegion =
  WorldYCoordinateToLineIndex(e.ClipRectangle.Bottom - scrollPositionY);
 if (maxLineInClipRegion >= this.documentLines.Count || maxLineInClipRegion == -1)
  maxLineInClipRegion = this.documentLines.Count - 1;
 TextLineInformation nextLine;
 for (int i = minLineInClipRegion; i <= maxLineInClipRegion; i++) {
  nextLine = (TextLineInformation)documentLines[i];
  dc.DrawString(nextLine.Text, mainFont, mainBrush, this.LineIndexToWorldCoordinates(i));
 }
base.OnPaint(e);
}

В середине этой перезагружаемой версии OnPaint() находится цикл, который перебирает все строки документа, вызывая метод Graphics.DrawString() для рисования каждой из них. Остальная часть этого кода связана в основном с оптимизацией рисования — обычный материал для определения, что действительно необходимо нарисовать вместо необдуманного приказания экземпляру Graphics перерисовать все.

Мы начинаем с проверки, имеются ли в документе какие-либо данные. Если данных нет, мы выводим краткое сообщение, говорящее об этом вызываем реализацию OnPaint() из базового класса и выходим. Если имеются данные, то мы начинаем проверять прямоугольник вырезания. Способ, которым это делается, состоит в вызове другого написанного нами метода WorldYCoordinateToLineIndex(). Мы рассмотрим этот метод позже, но по сути он получает заданную у-позицию относительно верха документа и определяет, какая строка документа будет выводиться в этой точке.

При первом вызове метода WorldYCoordinateToLineIndex() ему передается значение координаты е.ClipRectangle.Top - scrollPositionY. Это верх области вырезания, преобразованный в мировые координаты. Если возвращаемое значение будет -1, мы предположим, что нам нужно начать с начала документа (если верх области вырезания находится наверху граничного поля).

После того, как все это будет сделано, мы практически повторяем тот же процесс для низа прямоугольника вырезания, чтобы определить последнюю строку документа, которая находится внутри области вырезания. Индексы первой и последней строки хранятся соответственно в minLineInClipRegion и maxLineInClipRegion, поэтому мы можем просто выполнить цикл for между этими значениями, чтобы реализовать рисование. Внутри цикла рисования мы должны сделать приблизительно обратное преобразование для преобразования, выполненного методом WorldYCoordinateToLineIndex(). Задан индекс строки текста и нужно проверить, где она должна быть нарисована. Это вычисление является вполне простым, но мы поместили его в другой метод LineIndexToWorldCoordinates(), который возвращает требуемые координаты верхнего левого угла элемента. Возвращаемые координаты являются мировыми координатами, и это хорошо, так как мы уже вызвали метод TranslateTransform() на объекте Graphics, поэтому нам нужно передать ему при запросе вывода элемента мировые координаты, а не координаты страницы.

Оглавление книги


Генерация: 1.873. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз