¨ Если перо красное (8 младших бит цвета установлены в 1), а фон белый (то есть присутствуют все 3 компонента цвета — 3 байта установлены в 1), то результатом операции XOR будет цвет Cyan, так как красный компонент исчезнет (1+1=0), а оставшиеся компоненты (зеленый и синий), дают цвет Cyan;
00000000 00000000 00000000 11111111 // Перо - красное
00000000 11111111 11111111 11111111 // Фон - белый
00000000 11111111 11111111 00000000 // Результат операции XOR - Cyan
Если повторно пройтись красной линией по тому же месту (по линии цвета Cyan), то при сложении цветов единицы попадут на нули и цвет станет белым, так как все 24 бита (3 байта) цвета установятся в 1.
00000000 00000000 00000000 11111111 // Перо - красное
00000000 11111111 11111111 00000000 // Фон - Cyan
00000000 11111111 11111111 11111111 // Результат операции XOR - белый цвет
Итак, повторный проход стирает линию. В качестве упражнения повторите выкладки, при условии, что перо белое, а затем—черное. Такие упражнения шлифуют главные качества программиста—терпение и настойчивость. Черное перо являет вырожденный случай (эффект сохраняется, но контур линии отсутствует).
Тем не менее, для создания эффекта rubber-band обычно берут черное перо, но при этом задают стиль линии PS_DOT (пунктир) или PS_DASH (штрих), что в принципе равносильно черно-белому перу. Белые участки работают, как описано, а черные своей инертностью не мешают стирать и вновь воспроизводить контур линии.
Эффект переливания пунктира (натягивания и сжимания резинки) объясняется тем, что при изменении общей длины контура черные и белые участки меняют свое местоположение, узор линии начинается работать с разных стартовых позиций. Это и составляет суть эффекта rubber-band. Есть еще одно значение (R2_NOT) параметра функции SetROP2, которое успешно работает, но без эффекта резинки. Для реализации эффекта резинового прямоугольника введите в состав оконной процедуры такие переменные:
HDC hdc; // Контекст устройства, связанный с окном
PAINTSTRUCT ps; // Данные для рисования
static POINT ptOld; // Координаты курсора
static RECT rTarget; // Прямоугольник (позже он будет мишенью для копирования bitmap)
static RECT rClient; // Прямоугольник клиентской области окна
static HPEN hpenDot; // Описатель пунктирного пера
Удалите все вхождения переменной ptCenter. Вместо нее мы будем пользоваться прямоугольником rClient. Затем добавьте обработку события создания окна (WM_CREATE) и трех мышиных событий.
case WM_CREATE: // Реакция на создание окна
{
hpenDot = CreatePen (PS_DOT, 1, RGB(0, 0, 0));// Пунктирное перо для рисования динамического прямоугольника
break;
}
case WM_LBUTTONDOWN: // Реакция на нажатие левой кнопки
ClipCursor(&rClient); // Ограничиваем возможности перемещения курсора только клиентской областью окна
ptOld.x = LOWORD (lParam); // Запоминаем текущие координаты курсора
ptOld.y = HIWORD (lParam);
break;
case WM_MOUSEMOVE: // Реакция на движение курсора
{
if (!(wParam & MK_LBUTTON)) // Если не нажата левая кнопка мыши, уходим
return 0;
short x = LOWORD(lParam), y = HIWORD(lParam); // Текущие координаты курсора
hdc = GetDC(hWnd);
HPEN pOld = (HPEN)SelectObject (hdc, hpenDot); // Выбираем пунктирное перо в контекст устройства
HBRUSH bOld = (HBRUSH)SelectObject (hdc, GetStockObject(NULL_BRUSH));// Выбираем прозрачную кисть
SetROP2 (hdc, R2_XORPEN); // Инверсный режим смешивания цвета. Повторное рисование линии стирает старую линию
if (!IsRectEmpty (&rTarget)) // Сначала стираем старый прямоугольник мишени
Rectangle (hdc, rTarget.left, rTarget.top, rTarget.right, rTarget.bottom);
SetRect (&rTarget, ptOld.x, ptOld.y, x, y); // Вычисляем координаты нового прямоугольника - мишени
if (ptOld.x > x)
{
rTarget.left = x;
rTarget.right = ptOld.x;
}
if (ptOld.y > y)
{
rTarget.top = y;
rTarget.bottom = ptOld.y;
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.