Управление растровым изображением. Структура Windows-приложения. Развитие стартовой заготовки, страница 10

    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;

}