Смекни!
smekni.com

Основы графического вывода (стр. 9 из 26)

Для созданного пера будет назначен ближайший чистый цвет, который может быть воспроизведен данной аппаратурой. В реальных условиях он может отличаться от цвета, заданного вами.

Широкая линия проводится таким образом, что бы ее центр соединял указанные точки. Перо применяется не только для рисования линий, но и для рисования контура фигур. Если при этом используется широкая линия, то может быть удобно, что бы вся линия лежала внутри контура фигуры. Для таких целей предназначен стиль линии PS_INSIDEFRAME. Линии стиля PS_INSIDEFRAME отличаются еще одной особенностью: если ее ширина больше или равна 2 единицам устройства, то эта линия может рисоваться не чистым цветом, а смешанным.

При использовании Win32 API вы можете воспользоваться еще одной функцией для создания перьев:

HPENExtCreatePen (dwPenStyle, dwWidth, lpLogBrush, dwStyleCount, lpdwStyle); 1

typedef struct tagLOGBRUSH {

UINT lbStyle;

COLORREF lbColor;

LONG lbHatch;

} LOGBRUSH;

Перья, создаваемые этой функцией делятся на два типа: косметические (cosmetic) и геометрические (geometric). Для описания характеристик пера используется структура LOGBRUSH, обычно применяемая для описания кистей (см. раздел “Кисть”).

Косметические перья создаются, если в параметре dwPenStyle установлен стиль PS_COSMETIC. Они соответствуют тонким сплошным или прерывистым линиям (штриховым, штрих–пунктирным и пунктирным); всегда имеют ширину 1 пиксель (параметр dwWidth должен быть задан 1) и рисуются чистым цветом (цвет задается полем lbColor структуры LOGBRUSH; поле lbStyle обязательно должно быть BS_SOLID, а поле lbHatch не используется). Помимо стиля PS_COSMETIC надо задать один из дополнительных стилей:

Стили PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL, PS_INSIDEFARME в основном соответствуют уже рассмотренным стилям обычных перьев. (Для косметических ширина всегда равна 1 пикселю).

Стиль PS_ALTERNATE означает, что точки линии будут рисоваться через одну.

Если используется стиль PS_USERSTYLE, то два последних параметра функции ExtCreatePen задают стиль прерывистой линии: параметр lpdwStyle указывает на массив целых чисел, задающих длину штрихов и промежутков между ними; параметр dwStyleCount число записей в этом массиве. Внимание! длина штрихов и промежутков задается не в логических единицах, а в единицах устройства, непосредственно в процессе рисования линии.

Другой вид перьев — геометрические — создаются, если в параметре dwPenStyle указан стиль PS_GEOMETRIC. Такие перья могут быть произвольной толщины и цвета, включая узорчатые перья (рисунок на которых задается указанной кистью). Кроме того, при создании геометрических кистей есть возможность задать дополнительные стили. Так, в параметре dwPenStyle вы должны определить стиль PS_GEOMETRIC, стиль линии, стиль оформления окончаний и стиль сопряжения линий.

Стиль линии может быть PS_SOLID, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT, PS_NULL, PS_INSIDEFARME или PS_USERSTYLE. Стиль PS_ALTERNATE для геометрических перьев не поддерживается.

Стиль оформления окончаний играет роль для широких линий и может быть PS_ENDCAP_ROUND (конец линии полукруглый), PS_ENDCAP_SQUARE (в виде угла) и PS_ENDCAP_FLAT (прямой).

Стиль сопряжения линий влияет, если несколько последовательно проводимых отрезков сопрягаются под небольшим углом. Он может быть PS_JOIN_BEVEL (линии стыкуются под углом), PS_JOIN_ROUND (сопряжение скругляется) и PS_JOIN_MITER (сопряжение спрямляется). Если используется перо со стилем PS_JOIN_MITER, то дополнительно можно задать предельную величину спрямления сопрягаемых линий с помощью функции

BOOL SetMiterLimit (hDC, eNewLimit, lpeOldLimit); 1

BOOLGetMiterLimit (hDC, lpeOldLimit); 1

Величина спрямления задается относительно ширины линии.

Ширина геометрической линии может быть любой, она задается параметром dwWidth в логических единицах. Параметр lpLogBrush описывает кисть, которая задает цвет и узор линии; кисть может быть однотонной, смешанной, штрихованной или даже созданной по образцу — зависимому от устройства битмапу. Использование независимых от устройства битмапов в качестве образцов при описании пера недопустимо. О кистях и битмапах см. разделы “Кисть” и “Растровые изображения”.

Как и в случае косметических перьев, параметры dwStyleCount и lpdwStyle определяют стиль штриховки, если задан стиль линии PS_USERSTYLE, иначе они не используются. Однако в отличие от косметического пера, ширина штрихов и промежутков задается в логических единицах.

После использования созданного пера вы должны его уничтожить, причем перед этим он должен быть освобожден из контекста устройства (или весь контекст должен быть освобожден). Перо, как и все объекты GDI, уничтожается с помощью функции:

BOOL DeleteObject (hGDIobj);

BOOL DeletePen (hPen);


Текущая позиция пера

Следующий атрибут контекста устройства, используемый при рисовании линии, называется текущей позицией пера. Этот атрибут используется очень небольшим числом функций, поэтому мы вкратце рассмотрим их всех, даже если они не связаны с рисованием линий.

С первыми тремя функциями мы уже познакомились — они–то и используются для рисования линий.

DWORD MoveTo (hDC, nX, nY); 0

BOOL MoveToEx (hDC, nX, nY, lpPoint);

BOOL LineTo (hDC, nX, nY);

Помимо них с текущей позицией пера имеют дело функции GetCurrentPosition и GetCurrentPositionEx а также, в некоторых случаях, функции TextOut и ExtTextOut.

DWORD GetCurrentPosition (hDC); 0

BOOL GetCurrentPositionEx (hDC, lpPoint);

Эти функции возвращают позицию пера. Как обычно — GetCurrentPosition возвращает ее в двойном слове и применятся только в 16ти разрядном WindowsAPI, тогда как функция GetCurrentPositionEx возвращает результат в структуре типа POINT и может применяться как в WindowsAPI, так и в Win32 API.

Две другие функции — TextOut и ExtTextOut обычно не используют текущую позицию пера, вы должны им отдельно указывать позицию для вывода текста. Однако, иногда может быть удобно перейти в специальный режим привязки текста TA_UPDATECP (см. функцию SetTextAlign), при котором текст будет выводиться от текущей позиции, а после вывода текста текущая позиция переместится в конец выведенного фрагмента.


Цвет фона и режим заполнения фона

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

функциями для рисования линий — для заполнения промежутков между штрихами прерывистой линии

функциями вывода текста — для заполнения пространства под символами текста.

функциями, применяющими кисть — для заполнения фона между линиями штрихованных кистей.

Рисунок 5. Рисование прерывистых линий в разных режимах заполнения фона.

Для задания цвета фона и для выяснения текущего цвета вы можете воспользоваться функциями

COLORREF SetBkColor (hDC, crColor);

COLORREF GetBkColor (hDC);

Функции возвращают используемый ранее цвет фона. Аналогично перу, GDI будет использовать ближайший чистый цвет в качестве цвета фона.

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

int SetBkMode (hDC, nBkMode);

int GetBkMode (hDC);

GDI поддерживает два разных режима заполнения фона; один из них называется OPAQUE — это режим по умолчанию. В режиме OPAQUE промежутки заполняются текущим цветом фона, а в другом режиме, называемом TRANSPARENT, фон в промежутках не изменяется.

Режим рисования

Атрибут контекста устройства, называемый режим рисования, влияет на сам процесс рисования. Дело в том, что рисование на устройстве легко может быть представлено как операции над битовыми последовательностями, содержащими те или иные данные. Пока мы говорили о рисовании линии, подразумевая простейший перенос битового образа рисуемого объекта (линии) на другой битовый образ (уже имеющееся изображение).

Атрибут режим рисования задает правила, по которым GDI переносит информацию из одной битовой последовательности на другую. Так, помимо самого очевидного копирования возможны операции инверсии как уже имеющегося изображения, так и рисуемого, объединение с помощью различных битовых операций И (and), ИЛИ (or), ИСКЛЮЧАЮЩЕЕ ИЛИ (xor).

При рассмотрении процесса переноса изображения мы будем исходить из предположения монохромного устройства вывода, так как анализ процесса рисования на цветном устройстве выглядит громоздко. Говоря о монохромном устройстве мы будем обозначать светлую точку будем битом со значением 1, а для темную точку — 0.

При рисовании мы можем условно рассматривать три разные битовые последовательности:

исходное изображение, содержащее рисуемый объект, в документации называется pen (почему–то считается, что рисуется именно линия текущим карандашом — отсюда название — но, вообще говоря, режим рисования применяется для всех операций вывода графических примитивов — линий, эллипсов, многоугольников, текста и пр.);

контекст устройства, содержащий нарисованный ранее образ (хотя бы просто закрашенный фон), в документации называется destination;

результат — то изображение, которое будет находиться на контексте устройства после рисования;

Применительно к этим трем битовым последовательностям говорят о двоичной растровой операции (binary raster operation, ROP2), так как в формировании результата участвуют две исходных битовых последовательности.