Управление растровым изображением. Альтернативные способы перерисовки динамического прямоугольника. Работа с растровыми изображениями, страница 3

Развитие стартовой заготовки

Запустив приложение (Ctrl+F5), вы увидите окно минимального приложения. Заготовку надо развивать, внося требуемую функциональность. Например, задайте цвет фона, форму курсора и введите обработку сообщения о перерисовке. Цвет фона определяется классом окна, то есть структурой типа WNDCLASS. Если вы  заполните ее поле hbrBackground описателем кисти Windows, используемой  при закрашивании клиентской области окна, то система будет знать что делать при обработке сообщения WM_ERASEBKGND (стирание фона окна).

w.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);

Форму курсора можно задать одним из следующих способов (выберите только один):

w.hCursor = LoadCursor(0, IDC_ARROW);            // Готовый системный курсор

w.hCursor = LoadCursor(hInst, (char*)IDC_MYCUR); // Курсор из ресурсов приложения (его надо создать)

//===== Курсор из файла текущей папки

char s [MAX_PATH + 10];

GetCurrentDirectory(MAX_PATH, s);

strcat (s, "\\Hand.cur");  // Предполагается, что в папку приложения вы принесли файл с изображением курсора Hand.cur

w.hCursor = (HCURSOR)LoadImage (0,s,IMAGE_CURSOR,0,0,LR_LOADFROMFILE | LR_MONOCHROME);

Для рисования в окне надо в WndProc ввести ветвь, реагирующую на сообщение WM_PAINT. Например:

case WM_PAINT:

{

PAINTSTRUCT ps;                  // Данные для рисования

HDC hdc = BeginPaint(hWnd, &ps); // Получаем контекст устройства

Ellipse (hdc, 20,20,400,200);    // Рисуем эллипс

EndPaint (hWnd, &ps);       // Завершаем процесс рисования

break;

}

Если необходимо, чтобы рисунок всегда располагался в центре окна, то следует запоминать размеры окна (которые пользователь периодически изменяет) и использовать эти данные при рисовании. Например, введем в WndProc локальную переменную static POINT ptCenter; которая будет отслеживать изменения размеров окна. Это делается  в ветви обработки сообщения WM_SIZE.

case WM_SIZE:

ptCenter.x = LOWORD(lParam)/2;   // Распаковываем вспомогательный параметр сообщения

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;