¨ Bitmap, копируемый в контекст, связанный с окном, следит за размерами клиентской области и периодически (в обработке WM_SIZE) подстраивает свои размеры под них. Само изображение при этом имеет меньший размер и является частью клиентского контекста. Изображение перемещается мышью в пределах большого bitmap'а. В этом сценарии важно, что перемещение изображения происходит в контексте, который не отображается в окне (он в памяти), а не в контексте hdc (на глазах у пользователя).
¨ Bitmap, копируемый в контекст, связанный с окном, по бокам имеет поля цвета окна, которые используются как бульдозер, заглаживающий поверхность для рисования. При перемещении они стирают остатки старого изображения. В этом сценарии важно первоначально (один раз) закрасить фон и не слишком быстро перемещать изображение, чтобы размеров полей хватило на закраску огрехов.
Рассмотрим реализацию первого способа, так как он дает фундаментальное решение. В этом случае нам придется завести еще один (уже третий) контекст устройства hdcClient, который будет соответствовать всей клиентской области окна. Существующий контекст hMemDC уже занят исходным (неискаженным) изображением и его, видимо, не удастся модифицировать без потери производительности. Алгоритм использования трех контекстов в процессе перерисовки представляется таким:
¨ В контекст hdcClient выбираем новый bitmap, размеры которого соответствуют размерам клиентской области окна, и закрашиваем его цветом фона (PatBlt).
¨ Копируем в этот контекст (hdcClient) изображение, которое заготовлено в контексте hMemDC. Позиция изображения (в пределах hdcClient) и его размеры определяются прямоугольником rBmp, который редактируется пользователем, как и ранее. При копировании используем функцию StretchBlt.
¨ Копируем весь контекст hdcClient (то есть, всю клиентскую область окна) в контекст hdc, который связан с окном. Здесь достаточно использовать функцию BitBlt.
¨ Для отображения динамического прямоугольника, не соприкасающегося с изображением, добавим код в ветвь обработки сообщения WM_PAINT.
Оставим возможность изменять размер и позицию изображения, перенося его в соприкасающийся или не соприкасающейся прямоугольник, указанный пользователем. Во избежание ошибок ввода приведем полный текст оконной процедуры WndProc.
LRESULT WINAPI WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HDC hdc; // Контекст устройства, связанный с окном
RECT rTmp; // Временный прямоугольник
PAINTSTRUCT ps; // Данные для рисования
static HDC hMemDC; // Контекст устройства в памяти
static HDC hdcClient; // Контекст устройства в памяти
static POINT ptOld; // Координаты курсора
static RECT rBmp; // Прямоугольник bitmap-изображения
static RECT rTarget; // Прямоугольник – мишень копирования
static RECT rClient; // Прямоугольник клиентской области окна
static SIZE szSrc; // Исходные размеры bitmap
static SIZE szClient; // Размеры клиентской области
static HBITMAP hImg; // Описатель bitmap
static HBRUSH hbrBkgnd; // Описатель кисти для закраски фона
static bool bDrag; // Флаг перемещения
switch(msg)
{
case WM_CREATE:
{
hImg = LoadBitmap(GetModuleHandle(0), MAKEINTRESOURCE(IDB_BITMAP));
BITMAP bm;
GetObject (hImg, sizeof(BITMAP),&bm);
szSrc.cx = bm.bmWidth;
szSrc.cy = bm.bmHeight;
hdc = GetDC(hWnd); // Контекст устройства, связанный с окном
hMemDC = CreateCompatibleDC(hdc); // Контекст в памяти (изображение)
hdcClient = CreateCompatibleDC(hdc); // Контекст в памяти (клиентская область)
SelectObject (hMemDC, hImg);
ReleaseDC (hWnd, hdc);
hbrBkgnd = CreateSolidBrush (RGB(255,255,220));
SetRect (&rBmp, 1, 1, szSrc.cx-2, szSrc.cy-2);// Размеры прямоугольника с учетом рамки
break;
}
case WM_ERASEBKGND: return TRUE;
case WM_PAINT:
{
hdc = BeginPaint(hWnd, &ps);
HBITMAP hBmp = CreateCompatibleBitmap (hdc, szClient.cx, szClient.cy);
SelectObject (hdcClient, hBmp);
HBRUSH hOld = (HBRUSH)SelectObject (hdcClient, hbrBkgnd);
PatBlt (hdcClient, 0, 0, szClient.cx, szClient.cy, PATCOPY);
if (!IsRectEmpty (&rBmp))
{
StretchBlt (hdcClient, rBmp.left,rBmp.top,rBmp.right-rBmp.left,rBmp.bottom-rBmp.top,
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.