bDrag = true;
break;
case WM_MOUSEMOVE:
{
if (!(wParam & MK_LBUTTON))
return 0;
short x = LOWORD(lParam), y = HIWORD(lParam);
hdc = GetDC(hWnd);
if (bDrag) // Изображаем прямоугольник перетаскиваемого объекта
{
DrawFocusRect (hdc, &rBmp);
OffsetRect (&rBmp, x - ptOld.x, y - ptOld.y);
DrawFocusRect (hdc, &rBmp);
ptOld.x = x; ptOld.y = y;
}
else // Изображаем пустой прямоугольник - мишень для копирования изображения
{
if (!IsRectEmpty (&rTarget))
DrawFocusRect (hdc, &rTarget);
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;
}
DrawFocusRect (hdc, &rTarget);
}
ReleaseDC (hWnd, hdc);
break;
}
case WM_LBUTTONUP:
ClipCursor (0);
if (IntersectRect (&rTmp, &rBmp, &rTarget))
{
CopyRect (&rBmp, &rTarget);
InvalidateRect (hWnd, 0, TRUE);
}
if (bDrag)
{
bDrag = false;
InvalidateRect (hWnd, 0, TRUE);
}
break;
При закрытии окна следует освобождать динамические ресурсы Windows:
case WM_DESTROY:
DeleteObject (hbrBkgnd);
DeleteDC (hMemDC);
DeleteObject (hImg);
PostQuitMessage(0);
break;
Реакцию на WM_MOVE и WM_SIZE оставьте без изменений. Для того, чтобы все заработало, надо ввести в состав проекта ресурс какого-либо изображения.
1. Дайте команду Add4Resource4Bitmap4New4OK. Появится пустой bitmap,
2. Замените его идентификатор на IDB_BITMAP,
3. Дайте команду File4Open4Files of Type (Image Files),
4. Найдите где-либо на диске и откройте в рамках студии понравившееся изображене,
5. Скопируйте его (Ctrl+C), переключите окно (Ctrl+F6) и восстановите в окне IDB_BITMAP (Ctrl+V).
Запустите приложение (Ctrl+F5) и устраните возможные ошибки. Проанализируйте работу функции StretchBlt, изменяя размеры прямоугольника-мишени и перемещая в него существующее изображение. Попробуйте утащить изображение за пределы окна. Проверьте корректность отработки сообщений WM_SIZE и WM_MOVE.
Скопируйте весь файл с программой, переименуйте копию в DrawInverse.cpp, отсоедините от проекта старый файл и подсоедините новый. В ветвь обработки WM_MOUSEMOVE вновь вставьте установку растровой операции:
SetROP2 (hdc, R2_NOT);
Замените все вхождения:
DrawFocusRect (hdc, &rBmp);
на:
Rectangle (hdc, rBmp.left, rBmp.top, rBmp.right, rBmp.bottom);
а все вхождения:
DrawFocusRect (hdc, &rTarget);
на:
Rectangle (hdc, rTarget.left, rTarget.top, rTarget.right, rTarget.bottom);
Запустите приложение и убедитесь, что при перерисовке динамического прямоугольника цвета изображения инвертируются. Вы должны увидеть нечто похожее на то, что приведено на рисунке.
Объясните происходящее путем анализа булевских операций с компонетами цвета. Испытайте другие типы растровых операций, пользуйтесь документацией MSDN. Объясняйте, что происходит. Реализуйте какой-либо свой алгоритм управления изображением. Если вам понадобится перерисовывать все окно или его часть, то используйте способ, который заставляет Windows послать приложению сообщение WM_PAINT:
InvalidateRect (hWnd, 0, TRUE); // Объявляем недейсвительной всю клиентскую область, провоцируя перерисовку окна
Посмотрите справку по этой функции API и уясните смысл ее параметров.
В последней версии нашего приложения в моменты перерисовки содержимого динамического прямоугольника (то есть во время движения мыши при нажатой левой кнопке) мы видим, что изображение мерцает (flickers). Это происходит потому, что рисование производится на глазах у пользователя и он видит эффекты обновления рисунка, а именно: стирания поврежденной области (clip region) и создания нового изображения. Просмотрите код обработки события WM_MOUSEMOVE. Вы видите, что функция рисования
Rectangle (hdc, rBmp.left, rBmp.top, rBmp.right, rBmp.bottom);
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.