Создание простейшего графического редактора (Лабораторная работа № 20 по VisualC++ 2005), страница 4

Метафайлом называется хранящийся в памяти объект, поддерживающий собственный контекст устройства. Любые операции с контекстом  следует продублировать  в метафайле. Если позже потребуется повторить эти действия (при обновлении изображения) достаточно воспроизвести этот метафайл. В результате все графические операции повторяются, что приводит к автоматическому созданию нужных изображений.

           Есть класс CMetaFileDC. Его конструктор CMetaFileDC() конструирует объект этого класса.

           Метод  Create() создает контекст устройства Windows для метафайла и связывает его с объектом CMetaFileDC. После создания контекста устройства для метафайла в нем можно рисовать, дублируя графические операции в окне. Когда требуется обновить изображение, просто  нужно воспроизвести этот метафайл.

           Метод Close() закрывает контекст устройства и (что очень важно!)создает логический номер метафайла.

          Метод PlayMetaFile( логический_номер_метафайла)  воспроизводит метафайл по его логическому номеру.

                     Итак, для обновления изображения в окне нужно:

а) Включить в заголовочный файл документа указатель  pMetaFileDC на контекст устройства метафайла, который будет использоваться в программе.

Для этого выделить класс  Cgraf_painterDoc, вызвать контекстное меню, Add Variable. Указать тип переменной CMetaFileDC*   и   ввести имя указателя.

б) В конструктор  Cgraf_painterDoc() добавить выделение памяти и вызов метода Create() для создания нового объекта. 

Cgraf_painterDoc::Cgraf_painterDoc()

: pMetaFileDC(NULL)

{

    pMetaFileDC=new CMetaFileDC();

    pMetaFileDC->Create();

    // TODO: add one-time construction code here

}

В результате создан контекст устройства для метафайла,в котором будут дублироваться все действия пользователя.

в) Добавить в обработчики событий нажатия кнопки мыши и её перемещения

дублирование графических операций в метафайле. Все, что пользователь рисует на экране, должно дублироваться в метафайле. Это означает, что при каждом вызове метода для контекста устройства вида необходимо вызвать аналогичный метод для контекста метафайла

В результате обработчик отпускания левой кнопки мыши имеет вид:

void Cgraf_painterView::OnLButtonUp(UINT nFlags, CPoint point)

{

      Cgraf_painterDoc*pDoc=GetDocument();

      ASSERT_VALID(pDoc);

      DrawTo.x=point.x;

      DrawTo.y=point.y;

      CClientDC*pDC=new CClientDC(this);

      if(bLineFlag)

      {

            pDC->MoveTo(Anchor.x,Anchor.y);

            pDC->LineTo(DrawTo.x,DrawTo.y);

            pDoc->pMetaFileDC->MoveTo(Anchor.x,Anchor.y);

            pDoc->pMetaFileDC->LineTo(DrawTo.x,DrawTo.y);

      }

      if(bRectangleFlag)

      {

            pDC->MoveTo(Anchor.x,Anchor.y);

            pDC->Rectangle(Anchor.x,Anchor.y,DrawTo.x,DrawTo.y);

            pDoc->pMetaFileDC->MoveTo(Anchor.x,Anchor.y);

           pDoc->pMetaFileDC->Rectangle(Anchor.x,Anchor.y,DrawTo.x,DrawTo.y);

      }

      if(bEllipseFlag)

      {

      pDC->MoveTo(Anchor.x,Anchor.y);

      pDC->Ellipse(Anchor.x,Anchor.y,DrawTo.x,DrawTo.y);

      pDoc->pMetaFileDC->MoveTo(Anchor.x,Anchor.y);

pDoc->pMetaFileDC->Ellipse(Anchor.x,Anchor.y,DrawTo.x,DrawTo.y);

      }

      if(bFillFlag)

      {

            pDC->SelectStockObject(BLACK_BRUSH);

            pDC->FloodFill(Anchor.x,Anchor.y,RGB(0,0,0));

            pDoc->pMetaFileDC->SelectStockObject(BLACK_BRUSH);

            pDoc->pMetaFileDC->FloodFill(Anchor.x,Anchor.y,RGB(0,0,0));

      }

      delete pDC;//Удаляем указатель на текущий вид

      // TODO: Add your message handler code here and/or call default

      CView::OnLButtonUp(nFlags, point);

}

          Следует обратить внимание на то, что указатель pMetaFileDC  является элементом данных класса Cgraf_painterDoc. Поэтому, чтобы с его помощью вызывать методы класса CMetaFileDC, аналогичные методам для контекста устройства вида, описан указатель Cgraf_painterDoc*pDoc=GetDocument();

          Произвольная фигура рисуется при перемещении мыши. Поэтому аналогичное дублирование нужно добавить в соответствующем обработчике.