ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
Шрифт:
Эта логика отображает круг за пределами обработчика OnPaint, но очень важно понимать, что когда выполняется обновление формы, все такие круги стираются! Это разумно, поскольку соответствующая визуализация выполнялась в контексте события MouseDown. Значительно лучшим подходом Является создание в обработчике события MouseDown нового типа Point, который добавляется к некоторой внутренней коллекции (например, List‹T›), и только затем вызывается Invalidate. Тогда обработчик события Раint может просто "пройти" по коллекции и перерисовать каждый Point.
При таком подходе уже отображенные круги будут оставаться на месте, поскольку графическая визуализация обрабатывается в рамках события Paint. На рис. 20.1 показано окно тестового запуска этого приложения.
Рис 20.1. Простое графическое приложение
Исходный код. Проект BasiсPaintForm размещен в подкаталоге, соответствующем главе 20.
Освобождение объекта Graphics
Если вы внимательно читали несколько последних страниц, то могли заметить, что в некоторых примерах программного кода непосредственно вызывается метод Dispose объекта Graphics, тогда как в других примерах этого не делается. Поскольку тип Graphics работает с самыми разными неуправляемыми ресурсами, имеет смысл освободить указанные ресурсы как можно быстрее с помощью Dispose (не дожидаясь, когда это сделает сборщик мусора в процессе финализации). То же самое можно сказать о любом типе, поддерживающем интерфейс IDisposable. При работе с объектами Graphics нужно придерживаться следующих правил.
• Если объект Graphics был создан вами непосредственно, после окончания его использования его следует освободить.
• Если вы ссылаетесь на существующий объект Graphics, его освобождать не следует.
Для того чтобы это стало более понятным, рассмотрите следующий обработчик события Paint.
На данном этапе обсуждения не беспокойтесь о том, что некоторые элементы программной логики GDI+ могут быть для вас не вполне понятны. Однако обратите внимание на то, что здесь объект Graphics получается из файла *.jpg, загружаемого (с помощью статического метода Graphics.FromImage) из локального каталога приложения. Поскольку объект Graphics создается явно, после окончания использовании этого объекта лучше использовать Dispose, чтобы освободить внутренние ресурсы и сделать их снова доступными для использования другими компонентами системы.
Однако, заметьте, Dispose не вызывается явно для объекта, который был получен из поступающего на вход PaintEventArgs. Причина в том, что вы не создавали этот объект непосредственно и поэтому не можете гарантировать, что другие части программы не используют его. Очевидно, что при освобождении объекта, используемого в другом месте программы, могут возникать проблемы.
В связи с этим заметим, что если вы забудете вызвать метод Dispose для объекта, реализующего IDisposable, внутренние ресурсы будут освобождены позже, при обработке объекта сборщиком мусора (см. главу 5). В этом смысле освобождение объекта imgGraphics, строго говоря, не является необходимым. Так что, хотя явное освобождение объектов GDI+, созданных вами непосредственно, делает программный код совершеннее, мы с вами, чтобы сделать примеры программного кода в этой главе более краткими, не будем освобождать каждый тип GDI+ вручную.
Системы координат GDI+
Нашей следующей задачей будет рассмотрение координатных систем GDI+. В GDI+ определяются три разные системы координат, которые используются средой выполнения, при определении места размещения и размеров содержимого визуализации. Во-первых, есть так называемые мировые координаты (или внешние координаты). Мировые координаты представляют абстракцию размеров данного типа GDI+, независимую от единиц измерения. Например, при прорисовке прямоугольника с указанием для размерности (0, 0, 100, 100), вы на самом деле указываете прямоугольник размером 100x100 "единиц". Как вы можете догадаться, по умолчанию "единица" – это пиксель, однако ей можно назначить и другую единицу измерения (дюйм, сантиметр и т.п.),
Далее, есть страничные координаты (координаты страницы). Страничные координаты представляют смещение в применении к оригинальным мировым координатам. Это удобно тогда, когда вы не хотите вычислять смещение в своем программном коде вручную (вы не обязаны это делать). Например, если у вас есть форма, которая должна оставаться в границах 100x100 пикселей, вы можете указать страничную координату (100*100), чтобы визуализация выполнялась относительно точки (100*100). Тогда в своем базовом коде вы сможете просто указать мировые координаты (избежав, тем самым, необходимости вручную учитывать смещение),
Наконец, есть приборные координаты (координаты устройства). Приборные координаты представляют результат применения страничных координат к оригинальным мировым координатам. Эта координатная система используется для определения того, где именно будет показан соответствующий тип GDI+. При программировании с помощью средств GDI+ программист обычно мыслит в терминах мировых координат, которые являются базой для определения размеров и места размещения типа GDI+. Для визуализации в мировых координатах не требуется никаких специальных программных ухищрений – нужно просто передать значения измерений текущей операции визуализации,