Управление растровым изображением. Структура Windows-приложения. Развитие стартовой заготовки, страница 3

  ptCenter.y = HIWORD(lParam)/2;

  break;

Используем координату центра окна при вызове функции, изображающей эллипс (один из примитивов GDI).

Ellipse (hdc, ptCenter.x - 200, ptCenter.y - 100, ptCenter.x + 200, ptCenter.y + 100);

Flicker-Free Drawing

Избавится от мерцания (flicker) изображения в рамках GDI можно используя прием, который характеризуется упрощенной перерисовкой контура перемещаемого объекта и его обесцвечиванием. Иногда используют другой прием под названием rubber-band (резиновая лента). Вы видите производимый им эффект, когда мышью выцарапываете объекты на рабочем столе Windows. В нашем приложении будут использованы оба этих приема.

Тонким местом в понимании технологии rubber-band является особый режим рисования линий контура. Каждое положение перемещаемой линии рисуется дважды. Первый раз линия рисуется, второй—стирается, третий—рисуется, и т. д. Этот эффект достигается благодаря предварительной настройке контекста устройства, которую производит API-функция SetROP2.

Цифра 2 в имени функции — намек на фонетическую близость английских слов «two» и «to». Имя функции SetROP2 можно прочесть как: Set Raster Operation To (установи режим растровой операции в) значение, заданное параметром функции. Просмотрите справку по этой функции, чтобы узнать ее возможности при выборе режимов рисования (растровых операций).

Если функцию SetROP2 вызвать с параметром R2_XORPEN, то рисование будет происходить по законам логической операции XOR (исключающее ИЛИ). В булевой алгебре эта операция называется сложением по модулю два. Ее законы просты: 0+0=0; 0+1=1; 1+0=1; 1+1=0. Алгоритм рисования контура линии выглядит так:

¨  Цвет каждого пиксела (каждой точки растра) определяется путем суммирования цвета фона и цвета пера по законам операции XOR;

¨  Если перо красное (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;  // Описатель пунктирного пера