Электронная библиотека книг Александра Фролова и Григория Фролова.
Shop2You.ru Создайте свой интернет-магазин
Библиотека
Братьев
Фроловых

Графический интерфейс GDI в Microsoft Windows

© Александр Фролов, Григорий Фролов
Том 4, М.: Диалог-МИФИ, 1993, 288 стр.

[Назад] [Содеожание] [Дальше]

2.5. Области

В интерфейсе GDI есть средства, позволяющие приложениям создавать области достаточно сложной формы из прямоугольных, многоугольных и эллиптических областей. Такие области можно закрашивать или использовать в качестве маски при выводе графического изображения. В последнем случае область называется областью ограничения. Она должна быть выбрана в контекст отображения.

Создание области

Приложение может создать область прямоугольной формы, область в виде многоугольника, область эллиптической формы. Можно комбинировать область из двух других, выполняя при этом над областями логические операции объединения, пересечения и т. д.

Прямоугольная область

Для создания прямоугольной области предназначены функции CreateRectRgn и CreateRectRgnIndirect :

HRGN WINAPI CreateRectRgn(
   int nLeftRect, int nTopRect,
   int nRightRect, int nBottomRect);
HRGN WINAPI CreateRectRgnIndirect(const RECT FAR* lprc);

Обе эти функции создают область прямоугольной формы, размеры которой заданы координатами верхнего левого и правого нижнего углов (для функции CreateRectRgn) или при помощи структуры типа RECT (для функции CreateRectRgnIndirect). Функции возвращают идентификатор созданной области.

Заметьте, что область создается вне всякой связи с контекстом отображения. Область - это объект, принадлежащий GDI, поэтому его следует удалить после использования. Лучше всего для этого воспользоваться макрокомандой DeleteRgn , определенной в файле windowsx.h следующим образом:

#define DeleteRgn(hrgn) DeleteObject((HGDIOBJ)(HRGN)(hrgn))

Вы можете создать область в виде прямоугольника со скругленными углами, если воспользуетесь функцией CreateRoundRectRgn :

HRGN WINAPI CreateRoundRectRgn(
   int nLeftRect, int nTopRect,
   int nRightRect, int nBottomRect,
   int nWidth, int nHeight);

Первые четыре параметра аналогичны параметрам функции CreateRectRgn. Они определяют координаты углов прямоугольной области. Последние два параметра, nWidth и nHeight, предназначены, соответственно, для определения размеров воображаемого эллипса, формирующего скругленные углы.

Область в виде многоугольника

Можно создать область в виде произвольного многоугольника. Для этого следует воспользоваться функцией CreatePolygonRgn :

HRGN WINAPI CreatePolygonRgn(
   const POINT FAR* lppt, // адрес массива точек
   int cPoints,           // размер массива
   int fnPolyFillMode);   // режим заполнения

Функция CreatePolyPolygonRgn создает область, состоящую из нескольких многоугольников:

HRGN WINAPI CreatePolyPolygonRgn(
  const POINT FAR* lppt,  // адрес массива точек
  int FAR* lpnPolyCounts, // адрес массива количества точек
                          //    в многоугольниках
  int cPolygons);         // количество многоугольников

Назначение параметров описанных выше двух функций аналогично назначению параметров функций рисования многоугольников Polygon и PolyPolygon (за исключением того, что при создании области не требуется указывать идентификатор контекста отображения).

Область эллиптической формы

Область эллиптической формы (или, как частный случай, круглой формы) можно создать при помощи функции CreateEllipticRgn :

HRGN WINAPI CreateEllipticRgn(
   int nLeftRect, int nTopRect,
   int nRightRect, int nBottomRect);

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

Функция CreateEllipticRgnIndirect также используется для создания области в форме эллипса:

HRGN WINAPI CreateEllipticRgnIndirect(const RECT FAR* lprc);

В отличие от функции CreateEllipticRgn координаты прямоугольника задаются с помощью структуры типа RECT, указатель на которую передается через параметр lprc.

Комбинирование областей

Функция CombineRegion позволяет вам изменить существующую область, скомбинировав ее из двух других:

int WINAPI CombineRgn(
  HRGN hrgnDest, // новая область
  HRGN hrgnSrc1, // первая исходная область
  HRGN hrgnSrc2, // вторая исходная область
  int fnCombineMode); // режим комбинирования

Перед вызовом функции вам надо определить все три области. Функция объединит области hrgnSrc1 и hrgnSrc2, изменив соответствующим образом область hrgnDest.

Способ комбинирования областей зависит от значения параметра fnCombineMode:

Значение параметра fnCombineMode Способ образования области hrgnDest
RGN_AND Пересечение областей hrgnSrc1 и hrgnSrc2
RGN_OR Объединение областей hrgnSrc1 и hrgnSrc2
RGN_XOR Объединение областей hrgnSrc1 и hrgnSrc2 с исключением перекрывающихся областей
RGN_DIFF Область hrgnSrc1, которая не входит в область hrgnSrc2
RGN_COPY Область hrgnSrc1

В зависимости от результата выполнения операции функция CombineRegion может вернуть одно из следующих значений:

Значение Описание
ERROR Ошибка
NULLREGION Новая область пустая
SIMPLEREGION Новая область не является самопересекающейся (т. е. граница созданной области не пересекает саму себя)
COMPLEXREGION Создана самопересекающаяся область

Для облегчения комбинирования областей в файле windowsx.h определены макрокоманды, предназначенные для копирования, пересечения, объединения и вычитания областей. Все они созданы на базе только что описанной функции CombineRegion :

#define CopyRgn (hrgnDst, hrgnSrc) \
   CombineRgn(hrgnDst, hrgnSrc, 0, RGN_COPY)

#define IntersectRgn (hrgnResult, hrgnA, hrgnB) \
   CombineRgn(hrgnResult, hrgnA, hrgnB, RGN_AND)

#define SubtractRgn (hrgnResult, hrgnA, hrgnB) \
   CombineRgn(hrgnResult, hrgnA, hrgnB, RGN_DIFF)

#define UnionRgn (hrgnResult, hrgnA, hrgnB) \
   CombineRgn(hrgnResult, hrgnA, hrgnB, RGN_OR)

#define XorRgn (hrgnResult, hrgnA, hrgnB) \
   CombineRgn(hrgnResult, hrgnA, hrgnB, RGN_XOR)

Перерисовка области

Вы можете отметить область как требующую перерисовки, вызвав функцию InvalidateRgn . В результате этого приложению будет передано сообщение WM_PAINT .

Приведем прототип функции InvalidateRgn:

void WINAPI InvalidateRgn(HWND hwnd, 
  HRGN hrgn, BOOL fErase);

Через параметр hwnd следует передать идентификатор окна, содержащего обновленную область hrgn.

Параметр fErase определяет необходимость стирания фона окна перед перерисовкой. Если этот параметр имеет значение TRUE, фон стирается, если FALSE - нет.

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

void WINAPI ValidateRgn(HWND hwnd, HRGN hrgn);

Другие операции

Для изменения прямоугольной области можно воспользоваться функцией SetRectRgn , изменяющей координаты существующей прямоугольной области:

void WINAPI SetRectRgn(
  HRGN hrgn,
  int nLeftRect, int nTopRect,
  int nRightRect, int nBottomRect);

Изменение области выполняется быстрее ее удаления с последующим повторный созданием новой.

Для перемещения области предназначена функция OffsetRgn :

int WINAPI OffsetRgn(HRGN hrgn, int nX, int nY);

Эта функция сдвигает область на nX логических единиц по горизонтали и на nY логических единиц по вертикали, возвращая такие же значения, что и функция CombineRegion.

Вы можете сравнить две области при помощи функции EqualRgn :

BOOL WINAPI EqualRgn(HRGN hrgn1, HRGN hrgn2);

Эта функция возвращает TRUE, если области совпадают, и FALSE - если нет.

С помощью функции GetRgnBox можно узнать координаты воображаемого прямоугольника, в который вписана область:

int WINAPI GetRgnBox(HRGN hrgn, RECT FAR* lprc);

Эта функция возвращает такие же значения, что и функция CombineRegion

Иногда требуется определить, находится ли заданная точка или прямоугольная область внутри другой области. Это можно сделать при помощи функций PtInRegion и RectInRegion .

Функция PtInRegion возвращает TRUE, если точка (nX,nY) находится внутри области hrgn:

BOOL WINAPI PtInRegion(HRGN hrgn, int nX, int nY);

Аналогично для прямоугольной области:

BOOL WINAPI RectInRegion(HRGN hrgn, const RECT FAR* lprc);

Закрашивание области

Для закрашивания области кистью, выбранной в контекст отображения, предназначена функция PaintRgn :

BOOL WINAPI PaintRgn(HDC hdc, HRGN hrgn);

Функция FillRgn также закрашивает область, но, в отличие от функции PaintRgn, эта функция использует кисть, идентификатор которой передается ей в качестве параметра hbrush:

BOOL WINAPI FillRgn(HDC hdc, HRGN hrgn, HBRUSH hbrush);

С помощью функции FrameRgn вы можете обвести заданную область (закрасить ее границу), используя кисть hbrush:

BOOL WINAPI FrameRgn(HDC hdc, HRGN hrgn,
  HBRUSH hbrush, int nWidth, int nHeight);

Параметры nWidth и nHeight определяют, соответственно, ширину и высоту кисти в пикселах, используемой для рисования границы.

Функция InvertRgn инвертирует цвета в указанной области:

BOOL WINAPI InvertRgn(HDC hdc, HRGN hrgn);

Все эти функции возвращают TRUE при успешном завершении или FALSE при ошибке.

Графический редактор битовых изображений Paint Brush, который поставляется вместе с операционной системой Windows, умеет закрашивать внутренние области замкнутых фигур. Для закраски вам достаточно, находясь в соответствующем режиме редактора, указать мышью любую точку внутри фигуры.

Для реализации описанной выше операции в программном интерфейсе GDI предусмотрены функции FloodFill и ExtFloodFill.

Для функции FloodFill необходимо указать идентификатор контекста отображения hdc, координаты точки nX и nY, а также цвет контура clrref, ограничивающего область:

BOOL WINAPI FloodFill(HDC hdc,
  int nX, int nY, COLORREF clrref);

Функция возвращает TRUE при успешном завершении или FALSE при ошибке (ошибка возникает в том случае, когда указанная точка имеет цвет clrref или она лежит вне области ограничения данного контекста отображения).

Для закраски используется кисть, выбранная в контекст отображения.

Функция ExtFloodFill аналогична функции FloodFill:

BOOL WINAPI ExtFloodFill(HDC hdc,
  int nX, int nY, COLORREF clrref,
  UINT fuFillType);

Эта функция имеет дополнительный параметр fuFillType, определяющий способ закраски области. Параметр может принимать значения FLOODFILLBORDER или FLOODFILLSURFACE . В первом случае закрашивается внутренняя область фигуры, ограниченная контуром, имеющим цвет clrref (как и при использовании функции FloodFill). Во втором случае закрашивается вся область, имеющая цвет clrref.

Функция ExtFloodFill возвращает TRUE при успешном завершении или FALSE при ошибке. Если значение параметра fuFillType равно FLOODFILLBORDER, ошибка может возникнуть из-за тех же причин, что и при выполнении функции FloodFill. Если же значение параметра fuFillType равно FLOODFILLSURFACE, ошибка может возникнуть из-за того, что цвет точки (nX,nY) не равен clrref.

Область ограничения

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

int WINAPI SelectClipRgn(HDC hdc, HRGN hrgn);

В качестве значения параметра hrgn вы можете использовать значение NULL. В этом случае для ограничения вывода будет использована внутренняя область окна.

[Назад] [Содеожание] [Дальше]