Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
WinAPI.docx
Скачиваний:
49
Добавлен:
16.12.2018
Размер:
3.43 Mб
Скачать

4.7.4 Отсечения: прямоугольники и регионы

Регионы также могут принимать участие в отсечении. Функция InvalidateRect делает недействительным прямоугольную область дисплея и генерирует сообщение WM_PAINT. Например, вы можете использовать функцию InvalidateRect для обновления рабочей области и генерации сообщения WM_PAINT:

InvalidateRect(hwnd, NULL, TRUE);

Вы можете получить координаты недействительного прямоугольника, вызвав функцию GetUpdateRect, и вы можете сделать действительным прямоугольник в рабочей области, используя функцию ValidateRect. Когда вы получаете сообщение WM_PAINT, координаты недействительного прямоугольника доступны из полей структуры PAINTSTRUCT, которые заполняются при вызове функции BeginPaint. Этот недействительный прямоугольник также определяет "регион отсечения". Вы не можете рисовать за пределами региона отсечения.

Windows содержит две функции, похожие на InvalidateRect и ValidateRect, работающие с регионами, а не с прямоугольниками:

InvalidateRgn(hwnd, hRgn, bErase);

и

ValidateRgn(hwnd, hRgn);

Когда вы получаете сообщение WM_PAINT как результат того, что регион стал недействительным, регион отсечения не обязательно будет прямоугольным.

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

SelectObject(hdc, hRgn);

или

SelectClipRgn(hdc, hRgn);

Регион отсечения задается в координатах устройства.

GDI делает копию региона отсечения, поэтому вы можете удалить объект-регион после выбора его в контекст устройства. Windows содержит также несколько функций для манипуляций с регионом отсечения, таких как ExcludeClipRect для исключения прямоугольника из региона отсечения, IntersectClipRect для создания нового региона отсечения, который представляет собой пересечение предыдущего региона отсечения и прямоугольника, и OffsetClipRgn для перемещения региона отсечения в другую часть рабочей области.

4.7.5 Программа cover

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

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

Поскольку регионы всегда используют координаты устройства, программа COVER должна перестраивать регион каждый раз при получении сообщения WM_SIZE. Это может занять несколько секунд. Программа начинает работу, создавая четыре эллиптических региона, которые запоминаются в первых четырех элементах массива hRgnTemp. Затем программа строит три фиктивных региона:

hRgnTemp [4] = CreateRectRgn(0, 0, 1, 1);

hRgnTemp [5] = CreateRectRgn(0, 0, 1, 1);

hRgnClip = CreateRectRgn(0, 0, 1, 1);

Затем комбинируются два эллиптических региона слева и справа рабочей области:

CombineRgn(hRgnTem[4], hRgnTemp[0], hRgnTemp[1], RGN_OR);

Затем аналогично комбинируются два эллиптических региона сверху и снизу рабочей области:

CombineRgn(hRgnTem[5], hRgnTemp[2], hRgnTemp[3], RGN_OR);

Окончательно, эти два комбинированных региона объединяются в hRgnClip:

CombineRgn(hRgnClip, hRgnTemp[4], hRgnTemp[5], RGN_XOR);

Идентификатор RGN_XOR используется для исключения области пересечения из результирующего региона.

Затем, все шесть временных регионов удаляются:

for(i = 0; i < 6; i++)

DeleteObject(hRgnTemp[i]);

Обработка сообщения WM_PAINT проста, принимая во внимание результаты. Начало координат области вывода (viewport) устанавливается в центр рабочей зоны (чтобы сделать рисование линий более простым), и регион, созданный при обработке сообщения WM_CREATE, выбирается в контекст устройства в качестве региона отсечения:

SetViewportOrg(hdc, xClient / 2, yClient / 2);

SelectClipRgn(hdc, hRgnClip);

Теперь осталось только нарисовать линии — 360 штук, отстоящих друг от друга на один градус. Длина каждой линии — переменная fRadius, задается равной расстоянию от центра до угла рабочей области:

fRadius = _hypot(xClient / 2.0, yClient / 2.0);

for(fAngle = 0.0; fAngle < TWO_PI; fAngle += TWO_PI / 360)

{

MoveToEx(hdc, 0, 0, NULL);

LineTo(hdc,(int)(fRadius * cos(fAngle) + 0.5), (int)(-fRadius * sin(fAngle) + 0.5));

}

При обработке сообщения WM_DESTROY регион удаляется:

DeleteObject(hRgnClip);

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]