47952 (597372), страница 7
Текст из файла (страница 7)
Еще одна функция GDI предназначена для рисования дуг:
BOOL Arc (hDC, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd);
Для задания рисуемой дуги эллипса вы должны задать сначала сам эллипс, дуга которого будет изображаться, а затем задать начальную и конечную точки дуги. Эллипс задается описывающим его прямоугольником (причем нижняя и правая границы не включаются) — параметры xLeft, yTop, xRight и yBottom, а начальная и конечная точки задаются параметрами xStart, yStart и xEnd, yEnd.
Рисунок 4. Рисование дуг эллипсов
Начальная и конечная точки могут не лежать на эллипсе. В этом случае GDI вычисляет точку пересечения эллипса с отрезком, соединяющим центр эллипса с указанной вами точкой. Дуга будет рисоваться между точками пересечения отрезков, направленных от центра эллипса к начальной и конечной точкам дуги в направлении против хода часовой стрелки (см. раздел «Направление рисования дуг»).
В случае применения Win32 API вы можете использовать еще несколько функций для рисования линий. Так две новых функции предназначены для рисования дуг:
BOOL ArcTo (hDC, xLeft, yTop, xRight, yBottom, xStart, yStart, xEnd, yEnd); 1
BOOL AngleArc (hDC, nX, nY, dwRadius, eStartAngle, eSweepAngle); 1
Функция ArcTo аналогична функции Arc, за исключением того, что она сначала рисует отрезок от текущей точки до начальной точки дуги, затем рисует саму дугу и перемещает текущую точку в конечную точку нарисованной дуги. Функция AngleArc рисует дугу окружности, не эллипса. Для нее надо задать центр окружности (параметры nX, nY), радиус (dwRadius), начальный угол (eStartAngle) и угловую величину рисуемой дуги (eSweepAngle), в градусах. GDI не проверяет угловую величину дуги, она может превышать 3600.
Еще пара новых функций предназначена для рисования ломаных линий:
BOOL PolylineTo (hDC, lpPoints, nCount); 1
BOOL PolyPolyline (hDC, lpPoints, lpuCounts, nPolyCount); 1
Функция PolylineTo отличается от Polyline тем, что начинает рисование с отрезка от текущей точки до первой точки, указанной в массиве, а после прорисовки всех отрезков перемещает текущую точку в последнюю точку массива. Функция PolyPolyline может за одну операцию отобразить несколько ломаных линий. Координаты всех точек всех линий задаются массивом структур POINT (параметр lpPoints), число точек в каждой ломаной линии задается массивом целых чисел lpuCounts, а число ломаных, рисуемых этой функцией — параметром nPolyCount.
Кроме того в Win32 API существуют функции для рисования кривых Безье:
BOOL PolyBezier (hDC, lpPoints, cPoints); 1
BOOL PolyBezierTo (hDC, lpPoints, cPoints); 1
Функция PolyBezier рисует линию состоящую из сегментов кривых Безье. Для задания каждого сегмента требуется указать четыре точки: начальную, две направляющие и конечная. Так как рисуется линия из нескольких сегментов, то конечная точка одного сегмента является в свою очередь начальной точкой другого сегмента. Таким образом кривая будет определяться набором из Npt = 1 + Nsegments*3; здесь Npt — число точек для задания кривой, Nsegments — число сегментов в кривой.
Используя функцию PolyBezier вы должны задать массив точек, определяющих начальную точку, две направляющие и конечную точку для первого сегмента кривой, затем по две направляющих и одной конечной для каждого последующего сегмента. Текущая точка при этом не используется.
Функция PolyBezierTo отличается тем, что текущая точка используется в качестве начальной точки первого сегмента. В этом случае в массиве должно содержаться на одну точку меньше — только по две направляющих и одной конечной для каждого сегмента кривой. И, кроме того, после рисования кривой текущая точка будет перемещена в конечную точку последнего нарисованного сегмента.
Последняя рассматриваемая функция предназначена для рисования целого набора из прямых отрезков и кривых Безье за одну операцию:
BOOL PolyDraw (hDC, lpPoints, lpbyTypes, cCount); 1
Массивы структур POINT (lpPoints) и байтов (lpbyTypes) имеют одинаковое количество элементов; каждый элемент массива lpbyTypes определяет тип рисуемой линии из текущей точки до точки, задаваемой соответствующим элементом массива lpPoints. Допустимы следующие значения для типов линий:
| PT_MOVETO | линия не рисуется, текущая точка перемещается в указанную позицию |
| PT_LINETO | рисуется отрезок от текущей точки, до указанной; текущая точка перемещается в конечную точку отрезка. |
| PT_BEZIERTO | рисуется кривая Безье; для задания кривой надо определить подряд три точки типа PT_LINETO: первые две точки — направляющие, последняя — конечная; текущая точка будет начальная точка кривой, а после рисования текущая точка переместится в конец нарисованного сегмента. |
| PT_CLOSEFIGURE | этот флаг может быть объединен со значениями PT_LINETO или PT_BEZIERTO; при его указании фигура будет замкнута проведением отрезка от последней точки нарисованного сегмента до первой точки фигуры (точки типа PT_MOVETO или точки, заданной функцией MoveTo перед вызовом PolyDraw. |
Перо
Для проведения линий используется специальный объект GDI, который определяет вид проводимой линии, ее цвет и толщину. По аналогии с обычным рисованием на бумаге такой объект получил название перо (pen). Перо является объектом GDI, следовательно к нему применяются все правила работы с объектами GDI, рассмотренные ранее.
GDI предоставляет возможность использовать одно из трех стандартных перьев или создавать собственные перья, имеющие нужные свойства. Функция GetStockObject позволяет получить стандартное перо; они отличаются только цветом, проводимая ими линия всегда сплошная, шириной 1 единицу устройства (пиксель). Вместо функции GetStockObject можно использовать макрос GetStockPen из windowsx.h. Как и все стандартные объекты GDI эти перья нельзя уничтожать.
HANDLE GetStockObject (nIndex);
HPEN GetStockPen (nIndex); 2
| BLACK_PEN | — черное перо |
| WHITE_PEN | — белое перо |
| NULL_PEN | — прозрачное перо |
Куда больше возможностей предоставляют функции, создающие перья. Две из них — CreatePen и CreatePenIndirect отличаются только способом передачи параметров. Функция CreatePen получает все характеристики создаваемого пера в виде отдельных параметров, а функция CreatePenIndirect использует структуру LOGPEN, описывающую создаваемое перо. Функционально обе функции тождественны. Эта же структура используется функцией GetObject для получения информации о пере.
HPEN CreatePen (nPenStyle, nWidth, crColor);
HPEN CreatePenIndirect (lpLogPen);
typedef struct tagLOGPEN {
WORD lopnStyle; // стиль пера
POINT lopnWidth; // ширина линии
COLORREF lopnColor; // цвет пера
} LOGPEN;
Стиль пера может быть:
| PS_SOLID | | сплошная тонкая или толстая линия |
| PS_DASH | | штриховая тонкая линия |
| PS_DOT | | пунктирная тонкая линия |
| PS_DASHDOT | | штрих–пунктирная тонкая линия |
| PS_DASHDOTDOT | | штрих–точка–точка тонкая линия |
| PS_NULL | (прозрачный) | |
| PS_INSIDEFRAME | | сплошная тонкая или толстая линия |
Ширина пера задается в логических единицах, причем в случае функции CreatePenIndirect для задания толщины используется структура типа POINT, в которой используется только поле x, а поле y — нет. Ширина пера задается в логических единицах. Так как логическая единица в общем случае может не совпадать с физической, то для создания тонких перьев (ширина которых равна 1 пикселю или одной строке растра) надо указать требуемую ширину равной 0 — тогда будет создано перо шириной 1 пиксель. Все прерывистые линии (PS_DOT, PS_DASH, PS_DASHDOT, PS_DASHDOTDOT), шириной больше физической 1 воспроизводятся как PS_SOLID.
Для созданного пера будет назначен ближайший чистый цвет, который может быть воспроизведен данной аппаратурой. В реальных условиях он может отличаться от цвета, заданного вами.
Широкая линия проводится таким образом, что бы ее центр соединял указанные точки. Перо применяется не только для рисования линий, но и для рисования контура фигур. Если при этом используется широкая линия, то может быть удобно, что бы вся линия лежала внутри контура фигуры. Для таких целей предназначен стиль линии PS_INSIDEFRAME. Линии стиля PS_INSIDEFRAME отличаются еще одной особенностью: если ее ширина больше или равна 2 единицам устройства, то эта линия может рисоваться не чистым цветом, а смешанным.
При использовании Win32 API вы можете воспользоваться еще одной функцией для создания перьев:
HPEN ExtCreatePen (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
BOOL GetMiterLimit (hDC, lpeOldLimit); 1
Величина спрямления задается относительно ширины линии.














