static HBRUSH hbrBkgnd; // Описатель кисти для закраски фона
RECT rTmp; // Временный прямоугольник
Вы помните, что переменные типа static не уничтожаются при выходе из оконной процедуры? Введите ветвь обработки сообщения WM_CREATE (первоначальное создание окна):
case WM_CREATE:
{
hImg = LoadBitmap(GetModuleHandle(0), MAKEINTRESOURCE(IDB_BITMAP));// Загружаем bitmap из ресурсов
BITMAP bm; // Определяем его размеры с помощью структуры BITMAP
GetObject (hImg, sizeof(BITMAP),&bm);
szSrc.cx = bm.bmWidth;
szSrc.cy = bm.bmHeight;
hdc = GetDC(hWnd); // Добываем контекст устройства, связанный с окном
hMemDC = CreateCompatibleDC(hdc); // Создаем контекст в памяти, совместимый с hdc
SelectObject(hMemDC, hImg); // Выбираем bitmap в этот контекст
ReleaseDC (hWnd, hdc); // Освобождаем лимитированный ресурс системы
hbrBkgnd = CreateSolidBrush (RGB(255,255,220));// Кисть цвета фона (для стирания bitmap при его перемещении)
SetRect (&rBmp, 1, 1, nSrcWidth-2, nSrcHeight-2); // Размеры прямоугольника с учетом толщины рамки
break;
}
Введите ветвь обработки сообщения WM_ERASEBKGND (закрашивание фона окна):
case WM_ERASEBKGND:
{
hdc = (HDC)wParam; // Добываем контекст устройства, который прислала система
HBRUSH hOld = (HBRUSH)SelectObject (hdc, hbrBkgnd); // Выбираем нашу кисть, запоминая текущую
RECT r;
GetClientRect(hWnd, &r); // Определяем размеры клиентской области окна
PatBlt(hdc, r.left, r.top, r.right - r.left, r.bottom - r.top, PATCOPY); // Закрашиваем
SelectObject(hdc, hOld); // Возвращаем перо в контекст устройства
return TRUE;
}
Реакция окна на сообщение о перерисовке вызывает функцию StretchBlt, которая копирует изображение из одного контекста устройства (в памяти) в другой (связанный с окном). Эта функция, в отличие от BitBlt, способна растянуть или сжать изображение, подстраивая его под заданный размер.
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
if (!IsRectEmpty (&rBmp))// Копируем изображение из контекста в памяти в контекст окна, одновременно изменяя размеры
StretchBlt (hdc,rBmp.left,rBmp.top,rBmp.right-rBmp.left,rBmp.bottom-rBmp.top, // Куда
hMemDC, 0, 0, nSrcWidth, nSrcHeight, // Откуда
SRCCOPY); // Как
SetRectEmpty (&rTarget); // Обнуляем прямоугольник - мишень
EndPaint (hWnd, &ps);
break;
Для управления изображением с помощью мыши выберем такой алгоритм:
¨ Если пользователь захватил изображение, то он может его переместить в любое место клиентской области окна. Здесь надо использовать ограничитель перемещения курсора,
¨ Если пользователь щелкнул мышью вне изображения, то он может обозначить желаемый его размер. Здесь будем выявлять факт пересечения двух прямоугольников и переносить изображение в новый прямоугольник.
case WM_LBUTTONDOWN:
ClipCursor(&rClient);
ptOld.x = LOWORD(lParam);
ptOld.y = HIWORD(lParam);
if (PtInRect(&rBmp, ptOld))
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);
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.