hMemDC, 0, 0, szSrc.cx, szSrc.cy, SRCCOPY);
BitBlt (hdc, 0,0, szClient.cx, szClient.cy, hdcClient, 0, 0, SRCCOPY);
}
if (!IsRectEmpty (&rTarget))
DrawFocusRect (hdc, &rTarget);
SelectObject (hdcClient, hOld);
EndPaint(hWnd, &ps);
DeleteObject (hBmp);
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);
if (bDrag) // Перемещение изображения
{
OffsetRect (&rBmp, x - ptOld.x, y - ptOld.y);
ptOld.x = x; ptOld.y = y;
InvalidateRect(hWnd, 0, FALSE);
}
else // Динамический прямоугольник
{
hdc = GetDC(hWnd);
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);
bDrag = false;
if (IntersectRect (&rTmp, &rBmp, &rTarget))
{
CopyRect(&rBmp, &rTarget);
InvalidateRect(hWnd, 0, TRUE);
SetRectEmpty(&rTarget);
}
break;
case WM_DESTROY:
DeleteObject (hbrBkgnd);
DeleteDC (hMemDC);
DeleteDC (hdcClient);
PostQuitMessage(0);
break;
case WM_MOVE:
case WM_SIZE: // Узнаем и преобразовываем координаты клиентской области окна
{
GetClientRect(hWnd, &rClient);
POINT ptLT = { rClient.left, rClient.top };
POINT ptRB = { rClient.right, rClient.bottom };
ClientToScreen(hWnd, &ptLT);
ClientToScreen(hWnd, &ptRB);
SetRect (&rClient, ptLT.x, ptLT.y, ptRB.x, ptRB.y);
szClient.cx = rClient.right - rClient.left;
szClient.cy = rClient.bottom - rClient.top;
SetRectEmpty (&rTarget);
break;
}
default:
return DefWindowProc(hWnd,msg,wParam,lParam);
}
return 0L;
}
Запустите и проверьте качество перерисовки всех компонентов. Теперь вы знаете, как работает технология flicker-free drawing.
1. Подключите к проекту новый файл Gradient.cpp и отключите старый.
2. Введите в файл код, приведенный ниже.
3. Добавьте возможность плавного перетаскивания двух объектов, использующих градиентные кисти.
#pragma comment (lib, "msimg32.lib")
#include <windows.h>
#include "resource.h"
LRESULT WINAPI WndProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
TRIVERTEX vert[2] =
{
{ 20, 20, 0xff00, 0, 0, 0 },
{ 300,300, 0, 0, 0xff00, 0 },
};
GRADIENT_RECT rect;
rect.UpperLeft = 0;
rect.LowerRight = 1;
GradientFill (hdc, vert, 2, &rect, 1, GRADIENT_FILL_RECT_H);
TRIVERTEX v [4] =
{
{ 400, 20, 0xff00, 0xff00, 0, 0 },
{ 700, 20, 0, 0xff00, 0xff00, 0 },
{ 700, 200, 0, 0, 0xff00, 0 },
{ 400, 200, 0xff00, 0xff00, 0xff00, 0 },
};
GRADIENT_TRIANGLE tria[2] =
{
{ 0, 1, 2 },
{ 0, 2, 3 }
};
GradientFill (hdc, v, 4, &tria, 1, GRADIENT_FILL_TRIANGLE);
EndPaint(hWnd, &ps);
break;
}
case WM_DESTROY: PostQuitMessage(0); break;
default:
return DefWindowProc(hWnd,msg,wParam,lParam);
}
return 0L;
}
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
{
WNDCLASS w;
ZeroMemory(&w,sizeof(w));
w.lpszClassName = "My Class";
w.hInstance = hInst;
w.lpfnWndProc = WndProc;
w.style = CS_HREDRAW | CS_VREDRAW;
w.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH);
w.hCursor = LoadCursor(0, IDC_ARROW);
if (!RegisterClass (&w))
return FALSE;
HWND hWnd = CreateWindow(w.lpszClassName, "Gradient Brushes",
WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0,0,CW_USEDEFAULT,CW_USEDEFAULT,0,0, hInst,0);
MSG msg;
while (GetMessage(&msg,0,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return int msg.wParam;
}
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.