Рисование многоугольников
Для рисования многоугольников служит функция Polygon.
BOOL Polygon (
HDC hdc, II дескриптор контекста отображения
CONST POINT *lppt, II указатель на массив структурPOINT
int cPoinis II размер массива структурPOINT
};
Параметры функцииPolygon no своему смыслу аналогичны параметрам функцииPolyline.ФункцияPolygon не использует текущую позицию пера и не изменяет ее после завершения работы.
В массиве структурPOINT каждая вершина может быть указана только один раз. ФункцияPolygonавтоматически замыкает линию, образующую многоугольник.
5.7.3.4Выбор кисти
Для закрашивания внутренней области замкнутых фигур, можно использовать как встроенные кисти, так и создавать свои.
Для выбора встроенных кистей необходимо пользоваться макрокомандой GetStockBrush, определенной в файле windows.h следующим образом:
#define GetStockBrush(i) ((НBRUSH)GetStockObject(i) В качестве параметра для этой макрокоманды можно использовать следующие значения:
Значение i | Oписание | |
BLACK_BRUSH WHITE_BRUSH GRAY_BRUSH LTGRAY_BRUSH DKGRAY_BRUSH NULL_BRUSH HOLLOW_BRUS H | Кисть черного цвета Кисть белого цвета Серая кисть Светло-серая кисть Темно-серая кисть Бесцветная кисть, которая ничего не закрашивает Синоним для NULL BRUSH |
Прежде чем использовать полученную кисть, ее необходимо выбрать в контекст отображения. Это можно сделать, используя макрокомандуSelectBrush:
#define SelectBrush(hdc, hbr) ((HBRUSH)SelectObject((hdc), (HGDIOBJ)(HBRUSH)(hbr)))
Для создания цветной кисти необходимо воспользоваться функцией CreateSolidBrush:
HBRUSH CreateBrush (COLORREF cirref);
После использования кисти ее следует удалить, для освобождения памяти, не следует забывать, что перед удалением кисти, необходимо выбрать в контекст старую кисть. Для удаления кисти служит определенная в файле windows.h макрокоманда DeleteBrush.
#define DeleteBrush(hbr) DeleteObject((HGDIOBJ)(HBRUSH)(hbr))
Для штриховки внутренней области необходимо создать соответствующую кисть. HBRUSH CreateHatchBrush(int fnStyle, COLORREF clrref);
Параметр clrrеl определяет тип штриховки.
Стиль штриховки | Описание |
HS_BDIAGONAL HS_FDIAGONAL HS_DIAGCROSS HS_HORIZONTAL HS_VERTICAL HS_CROSS | Штриховка под углом а = 45* Штриховка под углом а = 135" Двойная штриховка под углом а = 45" и Р = 135* Штриховка горизонтальными линиями Штриховка вертикальными линиями Двойная штриховка горизонтальными и вертикальными линиями |
Очень легко создать кисть со своим рисунком штриховки создав кисть из битового изображения размером 8х8 пикселов. Используя для этих целей функцию
HBRUSH CreatePatternBrush (HBITMAP hBilmap);
Ниже представлено приложениеDraw, демонстрирующее некоторые графические возможности GDI.
Листинг
Файл RDraw.cpp
//======================================================================
// Приложение Rdaw
// Демонстрация использования функции рисования графических изображений
//=====================================================================
#define STRICT
#include <windows.h>
#include <windowsx.h>
// Прототипы функций
BOOL InitApp (HINSTANCE);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void DrawLines(HDC); // Рисование линий
void DrawPolyline(HDC); // Рисование полилиний
void DrawArc(HDC); // Рисование дуги эллипса
void DrawRectangles(HDC); // Рисование прямоугольников
void DrawPolygon(HDC); // Рисование полигонов
void DrawEllipse(HDC); // Рисование эллипса
void DrawCircle(HDC); // Рисование окружности
void DrawPie(HDC); // Рисование сектора эллипса
void DrawChord(HDC); // Рисование сегмента эллипса
// Имя класса окна
CCHAR szClassName[] ="DrawClass";
// Заголовок окна
CCHAR szWindowTitle[]="Приложение Rdraw";
// Размеры внутренней области окна
short cxClient, cyClient;
// Код выбранной строки меню "Draw"
int nFigures=0;
// Режим фона
int nBkMode=0;
// Код растровой операции
int nROP2 = R2_COPYPEN;
// ==================================================================
// Функция WinMain
//===================================================================
int WINAPI
WinMain(HINSTANCE hinstance,
HINSTANCE hPrevlnstance,
LPSTR IpszCmdLine,
int nCmdShow)
{
MSG msg; // Структура для работы с сообщениями
HWND hwnd; // Идентификатор главного окна приложения
// Определяем наличие загруженной копии приложения
if (FindWindow(szClassName, szWindowTitle))
return FALSE;
// Инициализируем приложение
if(!InitApp(hinstance))
return FALSE;
// Создаем главное окно приложения
hwnd = CreateWindow(
szClassName, // имя класса окна
szWindowTitle, // заголовок окна
WS_OVERLAPPEDWINDOW, //стиль окна
CW_USEDEFAULT, // задаем размеры и расположение
CW_USEDEFAULT, // окна, принятые по умолчанию
CW_USEDEFAULT,
CW_USEDEFAULT,
0, 0, hinstance, NULL);
if (!hwnd) return FALSE;
// Рисуем главное окно максимального размера
ShowWindow(hwnd, SW_MAXIMIZE);
UpdateWindow(hwnd);
// Запускаем цикл обработки сообщений
while(GetMessage(&msg, 0, 0, 0))
{
DispatchMessage(&msg);
}
return msg.wParam;
}
//===================================================================
// Функция InitApp // Выполняет регистрацию класса окна
//===================================================================
BOOL InitApp(HINSTANCE hinstance)
{
ATOM aWndClass; // атом для кода возврата
WNDCLASS wc; // структура для регистрации класса окна
// Записываем во все поля структуры нулевые значения
memset(&wc, 0, sizeof(wc));
// Подключение меню
wc.lpszMenuName = NULL;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
wc.lpszClassName = (LPSTR)szClassName;
aWndClass = RegisterClass(&wc);
// Регистрация класса
return (aWndClass !=0);
}
//=================================================================
// Функция WndProc
//=================================================================
LRESULT CALLBACK
WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM IParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (msg) {
// При изменении размеров окна сохраняем новые значения ширины и высоты
case WM_SIZE:
// Размер клиентской части окна по горизонтали
cxClient = LOWORD(IParam),
// Размер клиентской части окна по верикали
cyClient = HIWORD(IParam);
return 0;
// Рисование в окне
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
// Устанавливаем метрическую систему координат
// с началом координат в левом нижнем углу окна.
SetMapMode(hdc, MM_LOMETRIC);
SetViewportOrgEx(hdc, 0, cyClient, NULL );
// Устанавливаем режим отображения.
SetBkMode(hdc, nBkMode);
// Устанавливаем растровую операцию.
SetROP2(hdc, nROP2);
DrawLines(hdc); // прямые линии
/*
DrawArc(hdc); // дуга окружности
DrawRectangles(hdc); // прямоугольники
DrawPolygon(hdc); // полигон
DrawEllipse(hdc); // эллипс
DrawCircle(hdc); // окружность
DrawPie(hdc); // сектор эллипса
DrawChord(hdc); // сегмент эллипса
DrawPolyline(hdc); // полилиния
*/
// освобождаем контекст отображения
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
break;
}
return DefWindowProc(hwnd, msg, wParam, IParam);
}
Файл RDrawfn.cpp
//===================================================================
// Файл Rdrawfn.cpp
//===================================================================
//-----------------------------
// Функции для приложения Rdraw:
//------------------------------
# define STRICT
# include <windows.h>
# include <windowsx.h>
// Размеры внутренней области окна
extern short cxClient, cyClient;
//-------------------------------------------------
// DrawLines
// Рисование линий различной толщины и стиля
//--------------------------------------------------
void DrawLines(HDC hdc)
{
HPEN hpenW10, hpenW50;
HPEN hpenDot, hpenDash, hpenDashDot, hpenOldPen;
// 1. Создание перьев
// 1.1. перо толщиной 1 мм.
hpenW10 = CreatePen(PS_SOLID, 10, RGB(0,0,0));
// 1.2. перо толщиной 5 мм.
hpenW50 = CreatePen(PS_SOLID, 50, RGB(0,0,0));
// 1.3. пунктирное перо.
hpenDot = CreatePen(PS_DOT, 0, RGB(0,0,0));
// 1.4. штриховое перо.
hpenDash = CreatePen(PS_DASH, 0, RGB(0,0,0));
// 1.5. штрихпунктирное перо
hpenDashDot = CreatePen(PS_DASHDOT, 0, RGB(0,0,0));
// 2. Рисуем две линии различной толщины пером, находящиеся
// в контексте отображения.
// 2.1. помещаем перо в начальныю позицию
MoveToEx(hdc, 100, 100, NULL);
// 2.2. рисуем линию
LineTo(hdc, 600,100);
// 2.3. выводим поясняющий текст
TextOut(hdc, 700,100,
"PS_SOLID. Сплошная, толщиной 1 пиксел.", 38);
// 3. Перед рисованием различными перьями, запоминаем перо
// находившееся в контексте отображения и одновременно
// выбираем перо толщиной 1 мм.
hpenOldPen = SelectPen(hdc, hpenW10);
MoveToEx(hdc, 100, 200, NULL);
LineTo(hdc, 600, 200);
TextOut(hdc, 700, 200, "PS_SOLID. Сплошная, толщиной 1 мм.", 34);
// 4. Перебираем созданные нами перья
SelectPen(hdc, hpenW50);
MoveToEx(hdc, 100, 300, NULL);
LineTo(hdc, 600, 300);
TextOut(hdc, 700, 300, "PS_SOLID. Сплошная, толщиной 5 мм.", 34);
SelectPen(hdc, hpenDot);
MoveToEx(hdc, 100, 400, NULL);
LineTo(hdc, 600, 400);
TextOut(hdc, 700, 400, "PS_DOT. Пунктирная толщиной 1 пиксел.", 40);
SelectPen(hdc, hpenDash);
MoveToEx(hdc, 100, 500, NULL);
LineTo(hdc, 600, 500);
TextOut(hdc, 700, 500, "PS_DASH. Штриховая толщиной 1 пиксел.", 36);
SelectPen(hdc, hpenDashDot);
MoveToEx(hdc, 100, 600, NULL);
LineTo(hdc, 600, 600);
TextOut(hdc, 700, 600, "PS_DASHDOT. Штрихпунктирная толщиной 1 пиксел.", 46);
TextOut(hdc, 700, 800, "Для тренировки, попытайтесь использовать цвет.", 46);
// 5. Выбираем старое перо в контекст отображения
SelectPen(hdc, hpenOldPen);
// 6. Удаляем созданные нами перья
DeletePen(hpenW10);
DeletePen(hpenW50);
DeletePen(hpenDot);
DeletePen(hpenDash);
DeletePen(hpenDashDot);
}
//----------------------
// DrawPolyLine
// Рисование полилинии
//----------------------
void DrawPolyline(HDC hdc)
{
// Массив координат точек излома полилинии
POINT ptPoints[]=
{
{10, 10}, {100,310},
{40, 300}, {300, 15},
{135,340}, {113, 125},
{250, 137}, {300, 300},
};
// Рисуем ломаную линию
Polyline(hdc, ptPoints, sizeof ptPoints / sizeof ptPoints[0]);
}
//------------------------------
// DrawArc
// Рисование дуги эллипса
//------------------------------
void DrawArc(HDC hdc)
{
HPEN hpenW10, hpenOldPen;
// Создаем перо 1 мм
hpenW10 = CreatePen(PS_SOLID, 10, RGB(0,0,0));
// Выбираем созданное перо в контекст отображения и
// запоминаем перо установленное в контексте отображения
// по умолчанию.
hpenOldPen = SelectPen(hdc, hpenW10);
// Рисуем дугу
Arc(hdc,
1200, 600, // верхний левый угол прямоугольника
1900, 100, // нижний правый угол прямоугольника
1750, 650, //начало
1850, 0); //конец
// Выбираем старое перо в контекст отображения
SelectPen(hdc, hpenOldPen);
// Удаляем созданное перо DeletePen(hpenW10);
}
//---------------------------
// DrawRectangles
// Рисование прямоугольников
//----------------------------
void DrawRectangles(HDC hdc)
{
HPEN hpenW10, hpenOldPen;
HBRUSH hbrush, hbrushOldBrush;
POINT pPoint[2];
RECT rect={350, 500, 400};
// Рисуем прямоугольник вокруг внутренней области окна.
// Так как установлен метрический режим отображения, а
// размеры окна, передаваемые вместе с сообщением WM_SIZE,
// выражены в пикселах, выполняем преобразование физических
// координат в логические
pPoint[0].x = 0;
pPoint[0].y = cyClient;
pPoint[1].x = cxClient;
pPoint[1].y = 0;
DPtoLP(hdc, pPoint, 2);
// Создаем перо толщиной 1 мм и выбираем его в контекст отображения
hpenW10 = CreatePen(PS_SOLID, 10, RGB(0,0,0));
hpenOldPen = SelectPen(hdc, hpenW10);
// Рисуем прямоугольник
Rectangle(hdc, pPoint[0].x, pPoint[0].y, pPoint[1].x, pPoint[2].y);
// Выбираем серую кисть
hbrush = GetStockBrush(GRAY_BRUSH);
hbrushOldBrush = SelectBrush(hdc, hbrush);
// Рисуем прямоугольник закрашенный серым цветом
Rectangle(hdc, 100, 500, 300, 50);
// Создаем и выбираем кисть для штриховки
hbrush = CreateHatchBrush(HS_DIAGCROSS, RGB(0,0,0));
SelectBrush(hdc, hbrush);
// Рисуем заштрихованный прямоугольник
Rectangle(hdc, 50, 300, 500,100);
// Выбираем старое перо и кисть
SelectPen(hdc, hpenOldPen);
SelectBrush(hdc, hbrushOldBrush);
// Заштриховываем прямоугольную область кистью
// brush, которая НЕ ВЫБРАНА в контексте
FillRect(hdc, &rect, hbrush);
// Рисуем прямоугольник со скругленными углами
RoundRect(hdc, 550, 200, 800, 100, 50, 50);
// Удаляем созданные нами перо и кисть
DeletePen(hpenW10);
DeleteBrush(hbrush);
}
//---------------------------
// DrawPolygon
// Рисование прямоугольника
//------------------------------
void DrawPolygon(HDC hdc)
{
HBRUSH hbrush, hbrushOldBrush;
int nOldPolyFillMode;
// Координаты вершин первого многоугольника
POINT ptPoints1[]=
{
{10, 10}, {100, 310}, {40, 300},
{300, 15}, {135, 340}, {113,125},
{250, 137}, {300, 300}
};
POINT ptPoints2[] =
{
{310, 10}, {400 ,310}, {340, 300},
{600, 15}, {435, 340}, {413, 125},
{550,137}, {600, 300}
};
// Выбираем встроенную серую кисть
hbrush = GetStockBrush(GRAY_BRUSH);
hbrushOldBrush = SelectBrush(hdc, hbrush);
// Рисуем первый многоугольник в режиме заполнения
//ALTERNATE, установленном по умолчанию
Polygon(hdc, ptPoints1,
sizeof ptPoints1/sizeof ptPoints1[0]);
// Устанавливаем режим заполнения WINDING
nOldPolyFillMode = SetPolyFillMode(hdc, WINDING);
// Рисуем второй многоугольник
Polygon(hdc, ptPoints2,
sizeof ptPoints2/sizeof ptPoints2[0]);
// Восстанавливаем старый режим заполнения
SetPolyFillMode(hdc,nOldPolyFillMode);
SelectBrush(hdc, hbrushOldBrush);
}
//----------------------------
// DrawEllipse
// Рисование эллипса
//-----------------------------
void DrawEllipse(HDC hdc)
{
POINT pPoint[2];
// Эллипс будет вписан во внутреннюю область окна,
// поэтому определяем координаты углов в текущей
// (метрической) системе координат после выполнения
// преобразований.
pPoint[0].x = 0;
pPoint[0].y = cyClient;
pPoint[1].x = cxClient;
pPoint[1].y = 0;
DPtoLP(hdc, pPoint, 2);
// Рисуем эллипс
Ellipse(hdc, pPoint[0].x, pPoint[0].y, pPoint[1].x, pPoint[1].y );
}
//------------------------------
// DrawCircle
// Рисование сектора круга
//-------------------------------
void DrawCircle(HDC hdc)
{
// Рисуем эллипс вписанный в квадрат
Ellipse (hdc, 100, 600, 600, 100);
}
//------------------------------
// DrawPie
// Рисование сектора круга
//-----------------------------
void DrawPie(HDC hdc)
{
HPEN hpenW10, hpenOldPen;
// Создаем перо и выбираем его
hpenW10 = CreatePen(PS_SOLID, 10, RGB(0,0,0));
hpenOldPen = SelectPen(hdc, hpenW10);
// Рисуем сектор круга
Pie(hdc, 100, 600, 800, 100, 650, 650,750, 0);
// Выбираем старое перо и удаляем созданное
SelectPen(hdc, hpenOldPen);
DeletePen(hpenW10);
}
//-----------------------------
// DrawChord
// Рисование сегмента круга
//-----------------------------
void DrawChord(HDC hdc)
{
HPEN hpenW10, hpenOldPen;
hpenW10 =CreatePen(PS_SOLID, 10, RGB(0,0,0));
hpenOldPen = SelectPen(hdc, hpenW10);
// Рисуем сегмент круга
Chord(hdc,100,600, 800, 100, 650, 650, 750, 0);
SelectPen(hdc, hpenOldPen);
DeletePen(hpenW10);
}
Дата добавления: 2017-01-26; просмотров: 1524;