Чтение онлайн

на главную - закладки

Жанры

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

Ватсон Карли

Шрифт:

private void InitializeComponent {

 this.components = new System.ComponentModel.Container;

 this.Size = new System.Drawing.Size(300, 300);

 this.Text = "Draw Shapes";

 this.BackColor = Color.White;

}

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

Использование области вырезания

Пример приложения

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

До сих пор все хорошо. А что произойдет, когда перекрывающее окно (в данном случае Task Manager) будет удалено, так что окно

DrawShapes
будет снова полностью видно? Windows, как обычно, пошлет форме событие
Paint
, чтобы она себя перерисовала. Прямоугольник и эллипс находится в верхнем левом углу клиентской области и поэтому видны все время, так что в действительности нет ничего, что требуется сделать в данном случае, помимо перерисовки белой фоновой области. Однако Windows этого не знает. В той степени, в какой это касается Windows, необходимо перерисовать часть окна. Это означает, что надо инициировать событие Paint, которое вызывается в нашей реализации
OnPaint
.
OnPaint
будет затем пытаться излишне перерисовать прямоугольник и эллипс.

В таком случае фигуры не нужно перерисовывать. Причина этого связана с контекстом устройства. Ранее говорилось, что контекст устройства внутри объекта

Graphics
, передаваемого в метод
OnPaint
, будет оптимизирован операционной системой Windows для выполнения конкретной ближайшей задачи. Это означает, что Windows предварительно инициализирует контекст устройства информацией о том, какая область в действительности должна быть перерисована. Это прямоугольник, который был покрыт окном Task Manager на снимке экрана, приведенном выше. Во время использования GDI, область помеченная для перерисовки, называлась недействительной областью, но с появлением GDI+ терминология существенно изменилась, и эта область стала называться областью вырезания. Контекст устройства знает, какая это область, и поэтому прервет любые попытки рисования вне этой области и не будет передавать соответствующие команды рисования графической плате. Это звучит хорошо, но все равно здесь существует потенциальная потеря производительности. Мы не знаем какой объем обработки потребуется выполнить контексту устройства, чтобы определить, что рисование произойдет вне недействительной области. В некоторых случаях это может оказаться существенной величиной, так как определение того, какие пиксели необходимо изменить и в какой цвет может оказаться очень трудоемким (хотя хорошая графическая плата обеспечит аппаратное ускорение). Прямоугольник является достаточно легкой фигурой. Эллипс — труднее, поскольку необходимо вычислять положение кривой. Вывод текста потребует еще больших усилий, так как необходимо обрабатывать информацию в шрифте, чтобы определить форму каждой буквы, а каждая буква состоит из ряда линий и кривых, которые должны быть нарисованы по отдельности. Если, как в большинстве распространенных шрифтов, это будет шрифт с переменной шириной, т. е., когда у каждой буквы нет фиксированного размера и она занимает столько места, сколько ей требуется, то невозможно даже определить, сколько пространства займет текст, не выполнив предварительных громоздких вычислений

Вследствие этого запрос экземпляра

Graphics
выполнит некоторое рисование вне недействительной области, что почти наверняка будет бесполезным использованием процессорного времени и замедлит работу приложения. В хорошо спроектированном приложении код активно помогает контексту устройства, выполняя несколько простых проверок, чтобы убедиться, что обычная работа по рисованию действительно нужна, прежде чем вызывать подходящие методы экземпляра
Graphics
. В этом разделе мы создадим новый пример
DrawShapesWithClipping
, изменяя для этого пример
DisplayShapes
. В коде
OnPaint
будет сделана простая проверка достоверности, что недействительная область пересекла область рисования, и только в этом случае вызовутся методы рисования.

Сначала необходимо получить данные области

вырезания. Для этого используется дополнительное свойство
PaintEventArgs
. Свойство, называемое
ClipRectangle
, содержит координаты предназначенной для перерисовывания области, помещенные в экземпляр структуры
System.Drawing.Rectangle
.
Rectangle
является достаточно простой структурой, она содержит 4 представляющих интерес свойства:
Top
,
Bottom
,
Left
и
Right
. Они соответственно содержат вертикальные координаты верха и низа прямоугольника и горизонтальные координаты левого и правого краев.

Затем надо решить, какой тест будет использоваться для рисования. Здесь будет использован простой тест. Отметим, что прямоугольник и эллипс полностью содержатся внутри прямоугольника, который простирается в клиентской области от точки (0, 0) до точки (80, 130), в действительности до точки (82, 132), так как мы знаем, что линии могут отклоняться примерно на пиксель вне этой области. Поэтому будем проверять, что верхний левый угол области вырезания находится внутри этого прямоугольника. Если это так, то выполняется рисование. Если нет, то ничего не делается. Код выглядит следующим образом:

protected override void OnPaint(PaintEventArgs e) {

 Graphics dc = e.Graphics;

 if (e.ClipRectangle.Tор < 132 && e.ClipRectangle.Left < 82) {

Pen BluePen = new Pen(Color. Blue, 3);

dc.DrawRectangle(BluePen, 0, 0, 50, 50);

Pen RedPen = new Pen(Color.Red, 2);

dc.DrawEllipse(RedPen, 0, 50, 80, 60);

 }

 base.OnPaint(e);

}

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

OnPaint
более сложной, в этом случае повысится производительность, но код
OnPaint
при этом усложнится и потребует больше работы для своего создания. Однако почти всегда стоит провести некоторую проверку просто потому, что это помогает понять общую картину (например, в нашем примере мы узнали дополнительно, что рисунок никогда не выходит за пределы прямоугольника (0, 0) на (82, 132)). Экземпляр
Graphics
не имеет этого знания, он слепо следует командам рисования. Такое дополнительное знание означает, что имеются более полезные или эффективные проверки, чем те. что мог бы делать экземпляр объекта
Graphics
.

Измерение координат и областей

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

Rectangle
, которая используется для представления координат прямоугольника. GDI+ в действительности использует несколько аналогичных структур для представления координат или областей. Мы рассмотрим основные структуры, определенные в пространстве имен
System.Drawing
:

Структура Основные открытые свойства
struct Point
X, Y
struct PointF
X, Y
struct Size
Width, Height
struct SizeF
Width, Height
struct Rectangle
Left, Right, Top, Bottom, Width, Height, X, Y, Location, Size
struct RectangleF
Left, Right, Top, Bottom, Width, Height, X, Y, Location, Size
Поделиться:
Популярные книги

Девятый

Каменистый Артем
1. Девятый
Фантастика:
боевая фантастика
попаданцы
9.15
рейтинг книги
Девятый

Цеховик. Книга 2. Движение к цели

Ромов Дмитрий
2. Цеховик
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Цеховик. Книга 2. Движение к цели

На границе империй. Том 10. Часть 3

INDIGO
Вселенная EVE Online
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 10. Часть 3

Жена неверного маршала, или Пиццерия попаданки

Удалова Юлия
Любовные романы:
любовно-фантастические романы
4.25
рейтинг книги
Жена неверного маршала, или Пиццерия попаданки

Надуй щеки! Том 2

Вишневский Сергей Викторович
2. Чеболь за партой
Фантастика:
попаданцы
дорама
фантастика: прочее
5.00
рейтинг книги
Надуй щеки! Том 2

Жена на пробу, или Хозяйка проклятого замка

Васина Илана
Фантастика:
попаданцы
фэнтези
5.00
рейтинг книги
Жена на пробу, или Хозяйка проклятого замка

Попаданка для Дракона, или Жена любой ценой

Герр Ольга
Любовные романы:
любовно-фантастические романы
7.17
рейтинг книги
Попаданка для Дракона, или Жена любой ценой

Ни слова, господин министр!

Варварова Наталья
1. Директрисы
Фантастика:
фэнтези
5.00
рейтинг книги
Ни слова, господин министр!

По дороге на Оюту

Лунёва Мария
Фантастика:
космическая фантастика
8.67
рейтинг книги
По дороге на Оюту

(Не) моя ДНК

Рымарь Диана
6. Сапфировые истории
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
(Не) моя ДНК

Газлайтер. Том 17

Володин Григорий Григорьевич
17. История Телепата
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Газлайтер. Том 17

Адвокат вольного города 3

Кулабухов Тимофей
3. Адвокат
Фантастика:
городское фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Адвокат вольного города 3

Шлейф сандала

Лерн Анна
Фантастика:
фэнтези
6.00
рейтинг книги
Шлейф сандала

Беглец

Бубела Олег Николаевич
1. Совсем не герой
Фантастика:
фэнтези
попаданцы
8.94
рейтинг книги
Беглец