Получение описателя контекста устройства
В простейшем случае описатель контекста (контекст) может быть получен с помощью функций:
HDC GetDC(HWND hwnd);
HDC GetWindowDC(HWND hwnd);
HDC GetDCEx(HWND hwnd, HRGN hrgnClip, DWORD dwFlags);
Функции GetDC и GetDCEx возвращают контекст клиентской области окна (без заголовка, рамки и пр.). Контекст всего окна может быть получен с помощью функций GetWindowDC или GetDCEx с соответствующим флагом:
DCX_WINDOW – дать контекст всего окна, включая системную область;
DCX_PARENTCLIP – использовать видимую часть родительского окна;
DCX_CLIPCHILDREN – исключить подчиненные окна;
DCX_NORESETATTRS – не сбрасывать состояние контекста при его освобождении и т.д.
При этом поведение функций зависит также от некоторых установок стиля оконного класса:
CS_CLASSDC – использовать единственный разделяемый контекст для всех окон данного класса;
CS_OWNDC – использовать собственный контекст для каждого экземпляра окна;
CS_PARENTDC – использовать контекст и регион отсечения родительского окна и т.д.
Кроме получения контекста существующего окна можно создавать новые контексты, связанные с определенным устройством.
Функции
HDC CreateDC(LPCTSTR lpszDriver, LPCTSTR lpszDevice,
LPCTSTR lpszOutput, CONST DEVMODE* lpInitData );
HDC CreateCompatibleDC(HDC hPrimDC);
создают новый контекст, связанный с указанным устройством (CreateDC) или совместимым с известным контекстом (CreateCompatibleDC). Во втором случае если «образцовый» контекст не задан, то создается контекст в памяти (memory context), совместимый с текущими установками экрана. Возвращаемое значение – описатель контекста или NULL – в случае ошибки. Параметры:
lpszDriver – может быть DISPLAY для контекстов, связанных с экраном, и NULL для всех других устройств;
lpszDevice – логическое имя устройства в системе;
lpszOutput – имя устройства в файловой системе (в Win32 – NULL);
lpInitData – указатель на структуру DEVMODE с инициирующими данными для устройства, NULL – настройки по умолчанию;
hPrimDC – «образцовый» контекст, с которым будет совместим вновь создаваемый, если NULL – экран с текущими настройками.
По окончании работы с контекстом он должен быть освобожден (закрыт). Для контекстов, полученных с помощью функций Get..., используется функция
int ReleaseDC(HWND hwnd, HDC hdc);
которая освобождает «общие» и оконные контексты.
Для контекстов, созданных с помощью функций Create..., используется функция
int DeleteDC(HDC hdc);
возвращает 1 – при успешном завершении, 0 – при ошибке.
Многие характеристики действующего контекста могут быть получены с помощью функции GetDeviceCaps(), принимающей в качестве аргумента описатель контекста и индекс (номер) интересующего параметра (описываются системными константами) и возвращающей значение этого параметра.
Основные инструменты графической подсистемы
В среде Windows за формирование изображения отвечают так называемые инструменты, а функции рисования лишь задают их поведение. Инструменты являются системными объектами, но прикладная программа может произвольно создавать их и управлять ими.
К основным инструментам относятся:
– перо (Pen) – отображение контурных примитивов («карандаш»);
– кисть (Brush) – заполнение внутренних областей примитивов;
– шрифт (Font) – отображение символов и строк;
– битовая карта (Bitmap) – «готовые» растровые изображения.
Инструмент идентифицируется его описателем и создается соответствующей функцией вида Create..., которая возвращает этот описатель (NULL – признак ошибки). Количество создаваемых инструментов искусственно не ограничивается, но в любом контексте одновременно может быть активным только один инструмент каждого типа. Выбор инструмента отменить нельзя, но можно повторять его сколько угодно раз с любыми другими инструментами того же типа. Инструменты различного типа между собой взаимно независимы. Перед удалением инструмент следует дезактивировать, выбрав активным другой инструмент того же типа, например, сохраненный предыдущий.
Инструмент Pen
Для отображения контурных примитивов используется перо, выбранное в контексте, определяющее цвет, ширину и стиль линии, который может быть сплошным (solid), точечным (dotted) или пунктирным (dashed).
По умолчанию устанавливается одно из трех стандартных перьев, рисующих сплошные линии толщиной в единицу, выбранного цвета: BLACK_PEN – черное перо, WHITE_PEN – белое перо и NULL_PEN – пустое перо, которое ничего не рисует.
Определив переменную, например, hPen типа HPEN (описатель пера –handle to a pen): HPEN hPen; получить описатель одного из стандартных перьев, например белого пера, можно, вызывая функцию
hPen = GetStockObject (WHITE_PEN);
сделаем это перо текущим, вызвав функцию
SelectObject (hdc, hPen);
После этого все линии будут использовать белое перо до тех пор, пока не выберем другое перо в контекст устройства или пока не освободим контекст устройства.
Все вышесказанное можно совместить в одной инструкции:
hPen = SelectObject (hdc, GetStockObject (WHITE_PEN));
Если это первый вызов, функция SelectObject возвращает описатель того пера, которое уже было выбрано в контексте устройства; текущим пером становится белое, а переменная hPen получает описатель предыдущего (по умолчанию – черного) пера, вернуться к которому можно, используя вызов
SelectObject (hdc, hPen);
Для создания пера используются функции CreatePen или CreatePenIndirect (ExtCreatePen).
Функция CreatePen:
hPen = CreatePen (iPenStyle, iWidth, rgbColor);
параметр iPenStyle определяет стиль линии и может принимать одно из семи значений (семь стилей пера): PS_SOLID – сплошное, PS_DASH, PS_DOT, PS_DASHDOT, PS_DASHDOTDOT – штриховое, пунктирное и штрихпунктирное, PS_NULL – нерисующее (пустое) перо, PS_INSIDEFRAME – внутренняя обводка, в замкнутом контуре автоматически отступает внутрь в соответствии с толщиной линии.
Для стилей PS_SOLID, PS_NULL и PS_INSIDEFRAME параметр iWidth задает ширину пера, при iWidth = 0 – перо шириной в один пиксел.
Параметр rgbColor – цвет пера; для перьев всех стилей, кроме PS_INSIDEFRAME, преобразуется в ближайший чистый цвет, стиль PS_INSIDEFRAME позволяет использовать полутона при ширине больше 1.
Можно создать перо, определив структуру LOGPEN logpen («логическое перо» – logical pen), содержащую поля:
lopnStyle (UINT) – стиль пера;
lopnWidth (POINT) – ширина пера в логических единицах измерения;
lopnColor (COLORREF) – цвет пера.
Затем создаем перо, передавая адрес структуры в функцию CreatePenIndirect:
hPen = CreatePenIndirect (&logpen);
Получить информацию об уже существующем пере можно, используя функцию
GetObject (hPen, sizeof(LOGPEN), &logpen);
Функции CreatePen и CreatePenIndirect не требуют описателя контекста устройства. Эти функции создают логические перья, которые никак не связаны с контекстом устройства до тех пор, пока не вызвать функцию SelectObject.
Рассмотрим метод создания, выбора и удаления перьев. Предположим, в программе используются два пера – красное шириной 3 и черное точечное. Определим переменные для хранения описателей этих перьев:
static HPEN hPen1, hPen2;
В процессе обработки сообщения WM_CREATE создадим перья:
hPen1 = CreatePen (PS_SOLID, 3, RGB (255, 0, 0));
hPen2 = CreatePen (PS_DOT, 0, 0);
В процессе обработки сообщения WM_PAINT или когда есть действительный контекст устройства, выберем одно из этих перьев в контекст устройства и можем рисовать, используя его:
SelectObject (hdc, hPen2);
[функции рисования линий]
SelectObject (hdc, hPen1);
[другие функции рисования линий]
В процессе обработки сообщения WM_DESTROY удалить их:
DeleteObject (hPen1);
DeleteObject (hPen2);
Можно создать перья в процессе обработки сообщения WM_PAINT и удалить их после вызова EndPaint.
Можно объединить вызовы функций CreatePen и SelectObject в одну инструкцию:
SelectObject (hdc, CreatePen (PS_DASH, 0, RGB (255, 0, 0)));
Удалить перо можно, выбрав стандартное перо BLACK_PEN в контекст устройства и удаления значения, возвращаемого функцией SelectObject:
DeleteObject (SelectObject (hdc, GetStockObject (BLACK_PEN)));
Выбирая только что созданное перо в контекст устройства, сохраним описатель, возвращаемый функцией SelectObject:
hPen = SelectObject (hdc, CreatePen (PS_DASH, 0, RGB (255, 0, 0)));
Если это первый вызов, hPen – описатель стандартного черного пера, мы можем теперь выбрать его в контекст устройства и удалить созданное перо (описатель, возвращаемый вызовом функции SelectObject) в одной инструкции:
DeleteObject (SelectObject (hdc, hPen));
Инструмент Brush
Объект кисть – это битовый образ, свойства которого распространяются в горизонтальном и вертикальном направлениях при закрашивании области.
Имеется шесть стандартных (Stock) кистей: WHITE_BRUSH – белая, LTGRAY_ BRUSH – светло-серая, GRAY_ BRUSH – серая, DKGRAY_ BRUSH – темно-серая, BLACK_ BRUSH – черная и NULL_ BRUSH (HOLLOW) – пустая кисть.
Выбрать одну из стандартных кистей в контекст устройства можно аналогично выбору пера, определив переменную типа описателя кисти HBRUSH hBrush; получаем описатель кисти, например, GRAY_BRUSH:
hBrush = GetStockObject (GRAY_BRUSH);
Выберем эту кисть в контекст устройства:
SelectObject (hdc, hBrush);
Теперь внутренняя область рисуемых фигур будет закрашиваться серым.
Если необходимо нарисовать фигуру без рамки, выберем перо NULL_PEN:
SelectObject (hdc, GetStockObject (NULL_PEN));
А если только контур фигуры без закрашивания внутренней области, выберем кисть NULL_BRUSH:
SelectObject (hdc, GetStockObject (NULL_BRUSH));
Для создания сплошной (Solid) логической кисти:
hBrush = CreateSolidBrush (rgbColor);
Для создания штриховой (Hatch) кисти, состоящей из горизонтальных, вертикальных или диагональных линий:
hBrush = CreateHatchBrush (iHatchStyle, rgbColor);
параметр iHatchStyle – стиль штриховки: HS_HORIZONTAL, HS_VERTICAL, HS_BDIAGONAL – диагональная слева направо вверх; HS_FDIAGONAL – диагональная слева направо вниз; HS_CROSS – прямая сетка; HS_DIAGCROSS – диагональная сетка; в обеих функциях rgbColor – цвет штриховых линий.
Промежутки между штриховыми линиями закрашиваются в соответствии с режимом и цветом фона, если режим фона – OPAQUE, то цвет фона используется для закрашивания промежутков между штриховыми линиями, если режим фона – TRANSPARENT, то промежутки между штриховыми линиями не зарисовываются.
Можно создавать кисти, основанные на битовых шаблонах, используя функцию CreatePatternBrush:
hBrush = CreatePatternBrush (hBitmap);
Функция, включающая три рассмотренные ранее функции, строящие кисти:
hBrush = CreateBrushIndirect (&logbrush);
переменная logbrush – структура типа LOGBRUSH («логическая кисть» – logical brush), содержащая поля:
UINT lbStyle – стиль кисти: BS_SOLID – сплошная; BS_HOLLOW, BS_NULL – «пустая» (невидимая); BS_HATCHED – штрихованная; BS_PATTERN, BS_PATTERN8X8 – задаются битовой картой; BS_DIBPATTERN, BS_DIBPATTERN8X8, BS_DIBPATTERNPT – задаются битовой картой DIB (в Windows 95 размер шаблона ограничен 8´8 точек);
COLORREF lbColor – цвет кисти, для пустой или «шаблонной» кисти игнорируется, для кистей с DIB-шаблоном младшее слово определяет, следует ли интерпретировать его цвета как заданные цветовыми компонентами (DIB_RGB_COLORS) или как палитровые (DIB_PAL_COLORS).
Значение поля lbStyle определяет, как интерпретируются другие поля:
lbStyle | lbColor | lbHatch |
BS_SOLID | Цвет кисти | Игнорируется |
BS_HOLLOW | Игнорируется | Игнорируется |
BS_HATCHED | Цвет штриховых линий | Стиль штриховки |
BS_PATTERN | Игнорируется | Описатель битового шаблона |
Получить описатель логической кисти: SelectObject (hdc, hBrush);
Удалить созданную кисть: DeleteObject (hBrush);
Получить информацию о кисти:
GetObject (hBrush, sizeof (LOGBRUSH), &logbrush);
Инструмент Font
Более сложным инструментом является шрифт. Все символы в оконном интерфейсе формируются в соответствии с одним из зарегистрированных в системе шрифтов.
Физический шрифт – файл (образ в памяти) с описанием начертаний всех известных в данном шрифте символов. Логический шрифт – объект GDI, характеризуемый как физическим шрифтом, так и его конкретными характеристиками. Он же является и инструментом, отвечающим за формирование символов.
Для создания логического шрифта используется функция
HFONT CreateFont (int nHeight, int nWidth, int nEscapement,
int nOrientation, int fnWeight, DWORD fdwItalic, DWORD fdwUnderline,
DWORD fdwStrikeOut, DWORD fdwCharSet,
DWORD fdwOutputPrecision, DWORD fdwClipPrecision,
DWORD fdwQuality, DWORD fdwPitchAndFamily,
LPCTSTR lpszFace);
возвращающая описатель созданного инструмента (NULL – ошибка), параметры:
nHeight – основной размер (высота) шрифта в логических единицах: положительное значение определяет высоту знакоместа, отрицательное – высоту шрифта (после смены знака), нулевое – размер по умолчанию; при неточном соответствии требуемого размера выбирается наибольший, не превышающий требуемый;
nWidth – «приблизительная» ширина шрифта, если 0 – стандартная для выбранного основного размера;
nEscapement – направление вывода строки символов (угол между базовой линией и горизонтальной осью по часовой стрелке в десятых долях градуса);
nOrientation – ориентация отдельного символа (исчисление аналогично предыдущему параметру, в Windows 9x ориентация символов и направление вывода должны совпадать);
fnWeight – толщина символов в условных единицах от 0 до 1000, например: 0 (FW_DONTCARE) – стандартный (по умолчанию), 400 (FW_NORMAL, FW_REGULAR) – стандартная толщина, обычный шрифт, 700 (FW_BOLD) – жирный, выделенный, и т.д.;
fdwItalic, fdwUnderline, fdwStrikeOut – флаги, указывающие, является ли шрифт наклонным, подчеркнутым или перечеркнутым;
fdwCharSet – тип символьного набора: DEFAULT_CHARSET, ANSI_CHARSET, OEM_CHARSET и т.д. (национальные наборы символов);
fdwOutputPrecision – «точность вывода» символов, фактически предпочтение типа шрифта при наличии альтернативного выбора: OUT_DEFAULT_PRECIS, OUT_DEVICE_PRECIS и т.д.;
fdwClipPrecision – точность отсечения;
fdwQuality – качество вывода;
fdwPitchAndFamily – комбинация по «ИЛИ» двух групп параметров, действующих при неопределенном имени шрифта:
– питч (шаг символов) – 2 младших бита: DEFAULT_PITCH, FIXED_PITCH, VARIABLE_PITCH;
– «семейство» шрифта – 4 старших бита: FF_DONTCARE – по умолчанию, FF_MODERN – моноширинные шрифты, FF_ROMAN – «книжные» с засечками (переменный шаг), FF_SWISS – без засечек (переменный шаг), FF_SCRIPT – «рукописные» и курсивные;
lpszFace – имя шрифта, обычно совпадает с именем его дискового файла; если NULL – система подбирает шрифт, наиболее отвечающий заданным требованиям, иначе явно указанный шрифт перекрывает их.
Функция CreateFontIndirect (const LOGFONT* lplgFont); использует в качестве аргумента структуру с полями аналогичного назначения.
Параметры шрифта не включают цвет отображающего инструмента. Управление цветом выводимого текста осуществляется функциями
COLORREF SetTextColor (hdc, crColor);
COLORREF GetTextColor (hdc);
Базовой функцией вывода символа является
BOOL TextOut (hdc, nXStart, nYStart, lpString, cbString);
Позицией символа считается верхний левый угол его знакоместа.
Закрашивание пустот
Если выбранные перо или кисть не сплошные, то они не воздействуют на фоновые промежутки, например, между штрихами, однако эти промежутки заполняются фоновым цветом, для работы с которым служат функции
COLORREF SetBkColor(hdc, crColor);
COLORREF GetBkColor(hdc);
первая из которых устанавливает новый, а вторая – получает текущий фоновые цвета; признак ошибки – значение CLR_INVALID. Функция SetBkColor возвращает значение предыдущего цвета.
Функции
int SetBkMode (hdc, iBkMode);
int GetBkMode (hdc);
соответственно устанавливают новый или определяют текущий режим фона, 0 – признак ошибки; параметр int iBkMode – режим фона, по умолчанию белый (OPAQUE) – сначала рисуется фон, затем передний план; режим TRANSPARENT – отменяет заполнение пустот, в этом случае цвет фона игнорируется и пустоты заполняться не будут.
Рисование линий и кривых
Теоретически все, что необходимо драйверу устройства для рисования, это функции SetPixel и GetPixel.
Значительно более эффективным является использование стандартных функций рисования отрезков и других сложных графических операций.
На представление линий, созданных с использованием функций, влияют атрибуты контекста устройства: текущая позиция, перо, режим фона (для несплошных перьев), цвет фона (для режима фона OPAQUE) и режим рисования.
Функция
LineTo (hdc, xEnd, yEnd);
рисует отрезок прямой из текущего положения пера, определенного в контексте устройства, до точки (xEnd, yEnd), которая не включается в отрезок. В контексте текущее положение пера по умолчанию устанавливается в точку (0,0) и функция LineTo без предварительной установки текущей позиции нарисует отрезок, начинающийся в левом верхнем углу рабочей области окна.
Для рисования отрезка из точки (xStart, yStart) в точку (xEnd, yEnd) необходимо сначала для установки (изменения) текущего положения пера использовать функцию
MoveToEx (hdc, xStart, yStart, &pt);
pt – структура типа POINT, определяющая предыдущую позицию. После чего, используя LineTo (hdc, xEnd, yEnd); будет нарисован отрезок до точки (xEnd, yEnd), не включая ее в отрезок, и текущее положение пера установится в точку (xEnd, yEnd).
Узнать текущее положение пера можно с помощью функции
GetCurrentPositionEx (hdc, &pt);
Следующий фрагмент программы отображает в рабочей области окна сетку с интервалом в 100 пикселей, начиная от левого верхнего угла:
GetClientRect(hwnd, &rect); (см. Пример 1, Сообщение WM_PAINT);
for (x = 0; x < rect.right; x += 100) {
MoveToEx (hdc, x, 0, NULL);
LineTo (hdc, x, rect.bottom);
}
for (y = 0; y < rect.bottom; y += 100) {
MoveToEx (hdc, 0, y, NULL);
LineTo (hdc, rect.right, y);
}
Когда необходимо соединить отрезками массив точек pt размером cPoint, можно использовать функцию
Polyline (hdc, pt, cPoint);
Например, определим массив из 5 точек (10 значений), описывающих контур прямоугольника:
POINT pt [5] = { 100, 100, 200, 100, 200, 200, 100, 200, 100, 100 };
используем функцию Polyline (hdc, pt, 5). Следует обратить внимание, что первая и последняя точки совпадают.
Функция Polyline не учитывает и не изменяет текущее положение пера. Функция PolylineTo использует текущее положение для начальной точки и устанавливает текущее положение в конец последнего нарисованного отрезка. Предыдущий пример будет выглядеть
MoveToEx (hdc, pt[0].x, pt[0].y, NULL);
PolylineTo (hdc, pt + 1, 4);
Для рисования дуги эллипса (рис. П 6.2) используется функция
Arc (hdc, x1, y1, x2, y2, xStart, yStart, xEnd, yEnd);
в которой значения (x1, y1) задают левый верхний угол, (x2, y2) – правый нижний; (xStart, yStart) – начало дуги; (xEnd, yEnd) – конец дуги.
Рис. П 6.2. Фигура, нарисованная с использованием функции Arc
Чтобы нарисовать одну или более связанных кривых Безье, используются функции
PolyBezier (hdc, pt, iCount);
PolyBezierTo (hdc, pt, iCount);
pt – массив структур типа POINT. В функции PolyBezier первые четыре точки идут в таком порядке: начальная точка, первая контрольная точка, вторая контрольная точка, конечная точка кривой Безье. Каждая следующая кривая Безье требует три новых точки, поскольку начальная точка следующей кривой есть конечная точка предыдущей и т.д. Параметр iCount = 1+3*n – равен единице плюс три, умноженное на число отображаемых кривых.
Пример изображения графика функции sin
Программа содержит массив из 1000 структур POINT. В цикле от 0 до 999 член x структуры растет от 0 до cxClient. В каждом цикле член структуры определяет значение синуса и масштабируется до размеров клиентской области окна. Вся кривая целиком отображается с использованием одного вызова функции Polyline (рис. П 6.3).
Текст программы может быть следующим:
#include <windows.h>
#include <math.h>
#define NUM 1000
#define TWOPI (2 * 3.14159)
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static char szAppName[] = "Sin" ;
HWND hwnd ;
MSG msg ;
WNDCLASSEX wndclass ;
wndclass.cbSize = sizeof (wndclass) ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground=(HBRUSH) GetStockObject(WHITE_BRUSH);
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
wndclass.hIconSm = LoadIcon (NULL, IDI_APPLICATION) ;
RegisterClassEx (&wndclass) ;
hwnd = CreateWindow (szAppName, "Second Example",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0)) {
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg,
WPARAM wParam, LPARAM lParam)
{
static int cxClient, cyClient ;
HDC hdc ;
int i ;
PAINTSTRUCT ps ;
POINT pt [NUM] ;
switch (iMsg) {
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
MoveToEx (hdc, 0, cyClient / 2, NULL) ;
LineTo (hdc, cxClient, cyClient / 2) ;
for (i = 0 ; i < NUM ; i++) {
pt[i].x = i * cxClient / NUM ;
pt[i].y = (int) (cyClient / 2 * (1 - sin (TWOPI * i / NUM))) ;
}
Polyline (hdc, pt, NUM) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}
Результат работы программы:
Рис. П 6.3
Рисование замкнутых фигур
Рассмотрим функции для рисования замкнутых фигур:
Rectangle – прямоугольник; Ellipse – эллипс; RoundRect – прямоугольник со скругленными углами; Chord – дуга кривой эллипса, концы которой соединены хордой; Pie – кусок, вырезанный из эллипса; Polygon – многоугольник; PolyPolygon – множество многоугольников.
Контур фигуры рисуется текущим пером, а фигура закрашивается текущей кистью. По умолчанию это стандартная кисть WHITE_BRUSH.
Простейшей является функция рисования прямоугольника:
Rectangle (hdc, x1, y1, x2, y2);
(x1, y1) – координаты левого верхнего угла, (x2, y2) – правого нижнего угла.
Для рисования эллипса используется функция, имеющая те же параметры:
Ellipse (hdc, x1, y1, x2, y2);
Фигура, отображаемая функцией Ellipse (вместе с ограничивающим прямоугольником).
Функция для рисования прямоугольника со скругленными углами:
RoundRect (hdc, x1, y1, x2, y2, xEllipse, yEllipse);
имеет два дополнительных параметра: для рисования скругленных углов используется маленький эллипс, шириной xEllipse, высотой yEllipse. Фигура, отображаемая этой функцией, приведена на рисунке. Скругленные углы были нарисованы с использованием размеров эллипса, вычисленных по формулам
xEllipse = (x2–x1)/4; yEllipse = (y2–y1)/4;
Это простое приближение, но результаты скорее всего будут выглядеть не совсем правильно, потому что округлость углов более заметна при больших размерах прямоугольника.
Функции Chord (сегмент эллипса) и Pie (сектор эллипса) имеют одинаковые параметры:
Chord (hdc, x1, y1, x2, y2, xStart, yStart, xEnd, yEnd);
Pie (hdc, x1, y1, x2, y2, xStart, yStart, xEnd, yEnd);
При рисовании используется воображаемая линия для соединения точки (xStart, yStart – начало дуги) с центром эллипса. В точке, где эта линия пересекается с ограничивающим прямоугольником, начинается рисование дуги эллипса в направлении против часовой стрелки; аналогично используется воображаемая линия для соединения точки (xEnd, yEnd – конец дуги) с центром эллипса. В точке, где эта линия пересекается с ограничивающим прямоугольником, завершается рисование дуги.
В функции Chord соединяются конечные точки дуги, а в функции Pie соединяются начальная и конечная точки дуги с центром эллипса.
Фигуры, отображаемые функциями Chord и Pie, приведены на рис. П 6.3.
Рис. П 6.3. Фигуры, нарисованные с использованием:
а – функции Chord; б – функции Pie