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

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

Жанры

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

Ватсон Карли

Шрифт:

Более подробно эти новые структуры и методы объекта Graphics будут рассмотрены позже.

Выполнение данного кода приведет к следующему результату:

Экран иллюстрирует два момента. Первое: можно ясно видеть, что понимается под клиентской областью окна. Это белая область, которая была задействована в результате задания свойства

BackColor
. Отметим, что прямоугольник расположился в углу этой области, как и можно было ожидать при задании координат (0, 0). Второе, отметим, что верхняя часть эллипса слегка перекрывает прямоугольник,— это было трудно предвидеть из заданных в коде координат. Так, Windows размещаем линии, ограничивающие прямоугольник и эллипс. По умолчанию Windows
будет пытаться поместить линию на границе фигуры что не всегда можно сделать точно, так как линия должна проходить через пиксели (очевидно), но граница каждой фигуры теоретически лежит между двумя пикселями. В результате линии толщиной в один пиксель будут проходить точно внутри верхней и левой сторон фигуры, но вне нижней и правой сторон, значит, фигуры, которые, строго говоря, находятся рядом друг с другом, будут иметь границы, перекрывающиеся на один пиксель. Мы определили более широкие линии, поэтому перекрытие будет больше. Можно изменить поведение по умолчанию, задавая свойство
Pen.Alignment
, как отмечено в документации MSDN, но для наших целей достаточно поведения по умолчанию.

На рисунке показано также, что код сработал правильно. Кажется, что рисование невозможно выполнить проще. К сожалению, если действительно выполнить этот пример, можно будет заметить, что форма ведет себя немного странно. Все нормально, если просто оставить ее на месте или перемещать по экрану с помощью мыши. Попробуйте минимизировать форму а затем восстановить ее. Окажется, что нарисованные формы просто исчезнут. То же самое произойдет, если протащить другое окно через окно этого примера. Еще интереснее будет, если закрыть форму другим окном, так что оно закроет только часть фигур, а затем убрать его снова. Окажется, что временно скрытая часть исчезла и осталась только часть эллипса и часть прямоугольника.

Что же делать? Проблема возникает, если окно или его часть становятся скрытыми по какой-либо причине (например, оно минимизируется или закрывается другим окном), Windows обычно немедленно отбрасывает всю информацию, относящуюся к тому, что там было изображено. Система должна это делать, иначе используемая память для хранения данных экрана будет слишком большой. Типичный компьютер может работать с видеоплатой, настроенной для вывода 1024×768 пикселей, возможно, в режиме с 24-битовым цветом. Мы покажем, что означает 24-битовый цвет позже, но в данный момент можно сказать, что каждый пиксель на экране занимает 3 байта, т. е. 2.25 Мбайт для изображения экрана. Однако нет ничего необычного, если пользователь имеет во время работы более 10 минимизированных окон в своей панели задач, в худшем сценарии 20, каждое из которых занимает весь экран, если оно не минимизировано. Если бы Windows действительно хранил визуальную информацию, которую содержат эти окна, готовую на случай, если пользователь захочет их восстановить, то речь шла бы о 45 Мбайт. Сегодня хорошая графическая карта может иметь 64 Мбайта памяти, но еще пару лет назад 4 Мбайта считалось большим объемом для графической платы, а избыточные данные необходимо было хранить в основной памяти компьютера. Множество людей все еще используют старые машины. Очевидно, что для Windows было бы непрактично управлять интерфейсом своих пользователей подобным образом.

В тот момент, когда какая-либо часть окна становится скрытой, эти пиксели пропадают. Windows замечает, что окно (или некоторая его часть) скрыто, и когда система обнаруживает, что эта область больше не является скрытой, она запрашивает приложение, которое владеет окном, чтобы оно перерисовало его содержимое. Существуют исключения из этого правила, обычно для случаев, когда небольшая часть окна скрыта очень недолго (хорошим примером является выбор элемента из основного меню, когда этот элемент меню раскрывается внизу, временно закрывая часть окна ниже). Однако можно ожидать, что, если часть окна становится скрытой, то приложению придется перерисовать его позже.

Это проблема для нашего примера приложения. Мы поместили код рисования в конструктор

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

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

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

Рисование фигур с помощью OnPaint

Если приведенное выше объяснение заставило вас подумать, что рисование своего собственного пользовательского интерфейса будет очень сложной задачей, то не стоит волноваться. Это не так. Были приведены различные детали процесса, для того чтобы вы поняли, с какими проблемами столкнетесь. Но заставить приложение перерисовать себя, когда необходимо, — в действительности легкая задача.

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

Paint
. Интересно то, что класс
Form
уже реализовал обработчик для этого события, поэтому не нужно создавать свой собственный. Можно воспользоваться этой архитектурой, исходя из факта, что обработчик
Form1
для события
Paint
будет вызывать в процессе обработки виртуальный метод
OnPaint
, передавая в него единственный параметр
PaintEventArgs
. Это означает, что для выполнения рисования необходимо просто переопределить метод
OnPaint
. Мы создадим для этого новый пример, называемый
DrawShapes
. Как и раньше, определяем
DrawShapes
как приложение Windows, генерируемое с помощью Visual Studio.NET, и добавим следующий код класса
Form1
:

protected override void OnPaint(PaintEventArgs e) {

 Graphics dc = e.Graphics;

 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
объявлен как
protected
.
OnPaint
обычно используется внутри класса, поэтому нет необходимости любому другому коду вне класса знать о его существовании.

PaintEventArgs
является производным классом от
EventArgs
, используемого обычно для передачи информации о событиях.
PaintEventArgs
имеет два дополнительных свойства, из которых наиболее важным является экземпляр
Graphics
, уже настроенный и оптимизированный для рисования требуемой части окна. Это означает, что нам не нужно вызывать
CreateGraphics
, чтобы получить контекст устройства в методе
OnPaint
, — он уже существует. Мы вскоре рассмотрим другое дополнительное свойство, оно содержит более подробную информацию о том, какая область окна действительно нуждается в перерисовке.

В данной реализации метода

OnPaint
мы сначала получаем ссылку на объект
Graphics
из
PaintEventArgs
, затем рисуем фигуры так же, как это делалось раньше. В конце вызывается метод
OnPaint
базового класса. Этот шаг является важным. Мы переопределили
OnPaint
для выполнения нашего собственного рисования, но возможно, что Windows должен выполнить свою собственную работу в процессе рисования, и такая работа будет связана с методом
OnPaint
в одном из базовых классов .NET.

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

base.OnPaint
не оказывает никакого влияния на работу, но никогда не пытайтесь удалить вызов. Это может привести к некорректному завершению работы Windows и непредсказуемым результатам.

OnPaint
будет также вызываться, когда приложение впервые запускается и окно приложения выводится в первый раз, поэтому нет необходимости дублировать код рисования в конструкторе, хотя по-прежнему нужно задать здесь цвет фона и все другие свойства формы. Это обычно задается либо добавлением команды явно, либо заданием цвета в окне свойств Visual Studio.NET:

Поделиться:
Популярные книги

Последнее желание

Сапковский Анджей
1. Ведьмак
Фантастика:
фэнтези
9.43
рейтинг книги
Последнее желание

Ученичество. Книга 2

Понарошку Евгений
2. Государственный маг
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Ученичество. Книга 2

Адвокат Империи 7

Карелин Сергей Витальевич
7. Адвокат империи
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Адвокат Империи 7

Вонгозеро

Вагнер Яна
1. Вонгозеро
Детективы:
триллеры
9.19
рейтинг книги
Вонгозеро

Мастер 7

Чащин Валерий
7. Мастер
Фантастика:
фэнтези
боевая фантастика
попаданцы
технофэнтези
аниме
5.00
рейтинг книги
Мастер 7

Неудержимый. Книга IX

Боярский Андрей
9. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга IX

Двойник Короля 2

Скабер Артемий
2. Двойник Короля
Фантастика:
попаданцы
аниме
фэнтези
фантастика: прочее
5.00
рейтинг книги
Двойник Короля 2

Сумеречный Стрелок 2

Карелин Сергей Витальевич
2. Сумеречный стрелок
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Сумеречный Стрелок 2

Возвышение Меркурия. Книга 7

Кронос Александр
7. Меркурий
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Возвышение Меркурия. Книга 7

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

INDIGO
13. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 8. Часть 2

И вспыхнет пламя

Коллинз Сьюзен
2. Голодные игры
Фантастика:
социально-философская фантастика
боевая фантастика
9.44
рейтинг книги
И вспыхнет пламя

Кодекс Крови. Книга I

Борзых М.
1. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга I

Неучтенный. Дилогия

Муравьёв Константин Николаевич
Неучтенный
Фантастика:
боевая фантастика
попаданцы
7.98
рейтинг книги
Неучтенный. Дилогия

Черный Маг Императора 10

Герда Александр
10. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Черный Маг Императора 10