}
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.
¨ Создайте копию файла Step03.cpp, переименуйте ее в Step04.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);
работает в контексте hdc, то есть в том контексте, который связан с окном. Эта функция не только рисует контур прямоугольника пунктирным пером, но и закрашивает его внутреннюю область белой кистью. Напомним, что по умолчанию используется кисть цвета WINDOW (этот индекс соответствует белому цвету). Реальные же цвета изменяются в соответствии с включенной растровой операцией R2_NOT.
Если мы хотим, чтобы в процессе перетаскивания изображения, оно непрерывно и плавно перерисовывалось, то нам необходимо:
¨ Отменить закраску внутренности динамического прямоугольника в ветви WM_MOUSEMOVE. Для этого надо убрать два вызова функции Rectangle,
¨ При каждом событии WM_MOUSEMOVE вычислять новое положение изображения, и, не дожидаясь обработки события WM_LBUTTONUP (конец процесса перетаскивания), копировать изображение из контекста hMemDC (в памяти) в контекст hdc (связанный с окном).
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.