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

Вычисление размеров объектов и размера документа

Вычисление размеров объектов и размера документа

Мы возвращаемся теперь к примеру CapsEditor и разбираем методы CalculateLineWidths() и CalculateDocumentSize(), которые вызываются из метода LoadFile():

private void CalculateLineWidths() {
 Graphics dc = this.CreateGraphics();
 foreach (TextLineInformation nextLine in documentLines) {
  nextLine.Width = (uint)dc.MeasureString(nextLine.Text, mainFont).Width;
 }
}

Этот метод просто выполняется на каждой прочитанной строке и использует метод Graphics.MeasureString() для определения и сохранения значения величины горизонтального пространства экрана, которое требуется строке. Мы сохраняем значение, так как MeasureString() является весьма интенсивным с вычислительной точки зрения. Так как в нашем примере CapsEditor не слишком легко определить высоту и положение каждого элемента, то этот метод почти наверняка будет реализован, чтобы вычислить все эти величины.

Теперь, когда мы знаем размер каждого элемента на экране и можем вычислить приблизительное его положение, определим реальный размер документа. Высота, по существу, равна числу строк, умноженному на высоту каждой строки. Ширину необходимо определить просмотром всех строк, чтобы выявить самую длинную и взять ширину этой строки. Для высоты и ширины также желательно допустить небольшие поля вокруг выводимого документа, чтобы приложение выглядело более привлекательно. (Нежелательно, чтобы текст прикасался к одному из углов клиентской области.) Вот метод, который вычисляет размер документа:

private void CalculateDocumentSize() {
 if (!documentHasData) {
  documentSize = new Size(100, 200);
 } else {
  documentSize.Height = (int)(nLines*lineHeight) + 2*(int)margin;
  uint maxLineLength = 0;
  foreach (TextLineInformation nextWord in documentLines) {
   uint tempLineLength = nextWord.Width + 2*margin;
   if (tempLineLength > maxLineLength) maxLineLength = tempLineLength;
  }
  documentSize.Width = (int)maxLineLength;
 }
 this.AutoScrollMinSize = documentSize;
}

Этот метод сначала проверяет, есть ли данные для вывода. Если данных нет, мы слегка схитрим и зададим жестко кодированный размер документа такой величины, чтобы хватило места для выведения большими красными буквами предупреждения <Empty Document>. В противном случае необходимо воспользоваться методом MeasureString() для определения реального размера документа.

После этого размер документа сообщается экземпляру класса Form, задавая свойство Form.AutoScrollMinSize. Когда это сделано, за сценой происходит кое-что интересное. В процессе задания этого свойства клиентская область становится недействительной и инициируется событие Paint в связи с тем, что изменение размера документа означает необходимость добавить или изменить панели прокрутки, а также, что вся клиентская область почти наверняка будет перерисована. Это в полной мере иллюстрирует то, что было сказано ранее об использовании метода Form.Invalidate(). Если вернуться назад к коду LoadFile(), то станет понятно, что вызов метода Invalidate() в этом методе является на самом деле излишним. Клиентская область будет объявлена недействительной в любом случае, когда задается размер документа. Явный вызов метода Invalidate() в реализации метода LoadFile() оставлен для иллюстрации. Фактически в этом случае все, что будет делать вызванный метод Invalidate(), является ненужным запросом повторного события Paint. Однако это в свою очередь подтверждает, что Invalidate() дает Windows возможность оптимизировать производительность. Второе событие Paint не будет фактически инициировано: Windows увидит, что в очереди уже находится событие Paint, и сравнит запрошенные недействительные области, чтобы попробовать объединить их. В этом случае оба события Paint будут определять всю клиентскую область, поэтому ничего не нужно делать, и Windows спокойно удалит второй запрос Paint. Конечно, это действие займет какое-то процессорное время, но оно будет ничтожным по сравнению с тем, сколько времени потребуется для реального выполнения рисования.

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


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