|
|
|||||||||||||||||||||||||||||
|
Рисование в DC. Как избежать ошибокИсточник: cyberguru
Данная статья не может претендовать на полноту раскрытия принципов рисования в среде Microsoft Windows, она создана в помощь тем, кто делает свои первые шаги в этой области, с целью обратить внимание на основные моменты и предотвратить возможные (наиболее часто встречающиеся) ошибки. Примеры кода будут представлены в двух вариантах: с использованием WinAPI и MFC. 1. Получение DC (Контекста устройства)Рисование в Windows осуществляется в контексте устройства (DC). Существуют 4 типа DC: Display, Printer, Memory (Compatible DC) и Information. Первые 3 используются для рисования, Information DC - для получения информации об устройстве. В данной статье будет рассматриваться Display DC (обращение с Memory DC будет рассмотрено в следующей статье, которая сейчас в подготовке), а обращение с Printer DC - большая отдельная тема, которую может быть кто-нибудь из участников осветит здесь на форуме. :) Итак, нам требуется в некотором окне нарисовать нечто свое собственное, картинку, график, текст и т.д. Первым делом необходимо получить контекст для рисования. Для этого в WinAPI применяются следующие методы: WinAPI // Получить DC клиентской области окна по его хэндлу В MFC классом "оберткой" для DC служит класс CDC. Для получения объекта CDC какого либо окна, в классе CWnd существуют следующие методы: MFC // Получить DC клиентской области окна Из приведенных методов получения DC наиболее часто используется GetDC, т.к. обычно рисование происходит в клиентской части. ВАЖНО: Любой DC, полученный по GetDC или GetWindowDC должен быть потом освобожден через вызов ReleaseDC. В противном случае происходят утечки ресурсов GDI, что при долгом времени работы програмы неизбежно приведет к глюкам при рисовании. Также, надо отметить, что ReleaseDC должно вызываться только для DC, полученных по GetDC или GetWindowDC. WinAPI // hWnd - хэндл окна, DC которого нам необходим MFC // m_Button1 - член класса, объект типа CButton 2. Ресурсы GDI. Выбор ресурсов в DC.Рисование в DC происходит посредством ресурсов GDI, таких как Pen, Brush, Font и Bitmap. Остальные типы ресурсов являются специфическими и не будут рассмотрены в данной статье. Под каждый из этих типов в Windows заведен соответствующий тип данных: HPEN, HBRUSH, HFONT и HBITMAP. В WinAPI для универсализации каждый из приведенных типов приводится к типу HGDIOBJ как в качестве параметра функций, так и в качестве возвращаемого значения. В MFC каждый тип представлен соответствующим классом: CPen, CBrush, CFont и CBitmap. Базовым для всех этих классов является класс CGdiObject. Большинство функций рисования в Windows использует выбранные в DC объекты, так например LineTo использует выбранный в DC Pen, ExtFloodFill - Brush, а TextOut - Font. Соответственно, чтобы рисовать нужными нам цветами и стилями, требуется выбрать в нужном нам DC наши собственные объекты, которые естественно, перед этим необходимо создать. Опущу сам момент создания объектов GDI, т.к. рассмотреть весь спектр функций, предусмотренный для этих целей в Windows, в рамках данной статьи достаточно трудно, а неполный охват этих функций выглядел бы нелогично. Напротив, уделю внимание возможным ошибкам при их использовании. Практика показывает, что как раз с созданием объектов проблемы возникают гораздо реже, чем при их использовании. Несмотря на все разнообразие способов создания объектов GDI, существует лишь один метод их удаления. Все объекты, созданные по методам CreateXXXX (CreatePen, CreateBrushIndirect, …) должны быть удалены методом DeleteObject. Для объектов, полученных по GetStockObject или CGdiObject::CreateStockObject вызывать DeleteObject необязательно, хотя ошибкой это не является. WinAPI BOOL DeleteObject (HGDIOBJ hgdiObj); MFC BOOL CGdiObject::DeleteObject(); Замечание: для объектов MFC CGdiObject::DeleteObject вызовется автоматически в деструкторе. То есть этот метод можно не вызывать для объектов, создающихся однократно. Для выбора объекта в DC используются следующий методы: WinAPI //Выбрать объект в DC MFC //Выбрать Pen в DC Все методы SelectObject возвращают объект GDI, который был выбран в DC перед этим. ВАЖНО
2) Вызов DeleteObject для объекта, который в данный момент выбран в DC к успеху не приведет. Перед удалением объект обязательно должен быть освобожден из DC. WinAPI // Получаем DC для рисования MFC // Получаем DC для рисования ВАЖНО
Что не надо делать в MFC:
Все это является примерами часто встречающихся ошибок. HGDIOBJ CGdiObject::Detach(); Этот метод используется для "отсоединения" от объекта класса CGdiObject(CPen, CBrush и т.д.) хэндла объекта GDI. При этом сам хэндл(а значит, и объект GDI) не удаляется. Пример использования метода Detach: // Функция создаст и вернет хэндл GDI объекта Font Ссылки по теме
|
|