CRect m _ EnclosingRect ;//прямоугольник, описывающий элемент



public:

  CElement();

  virtual ~CElement();

  virtual void Draw(CDC* pDC){}// виртуальная операция рисования

CRect GetBoundRect() const;// получить ограничивающий прямоугольник

};

5. Каждый элемент будет хранить информацию об описывающем прямоугольнике в переменной m_EnclosingRect базового класса. Для определения ограничивающего прямоугольника с учетом толщины пера реализуйте метод GetBoundRect в файле Element . cpp:

CRect CElement::GetBoundRect() const

{

CRect boundingRect(m_EnclosingRect);// переменная для хранения ограничивающего прямоугольника

boundingRect.InflateRect(m_PenWidth,m_PenWidth);//расширить прямоугольник на ширину пера

return boundingRect;

}

6. Выделите приложение mfc2 в окне классов и нажатием ПК мыши вызовите контекстное меню. В меню выберите пункт «Добавить|Класс». В появившемся окне выберите шаблон «Класс C++». Нажмите кнопку «Добавить».

7. Введите имя класса CLine, в поле базовый класс – CElement.В поля Файл.h и Файл.cpp выберите соответственно Element. h и Element. cpp.

8. В описание класса CLine добавьте следующий код:

class CLine : public CElement

{

public:

  CLine(void);

  ~CLine(void);

  virtual void Draw(CDC* pDC);// Функция отображения линии

CLine (const CPoint& start,const CPoint& end,COLORREF aColor);// конструктор объекта линии

protected :

  CPoint m_StartPoint;

  CPoint m_EndPoint;

};

9. В файле Element. cpp реализуйте конструктор класс CLine:

CLine::CLine(const CPoint& start,const CPoint& end,COLORREF aColor):m_StartPoint(start),m_EndPoint(end)

{

  m_PenWidth=1;

  m_Color=aColor;

//Определение описывающего прямоугольника

  m_EnclosingRect=CRect(start,end);

  m_EnclosingRect.NormalizeRect(); }

10. Реализуйте метод Draw класса CLine. Ниже приведен программный код:

void CLine::Draw(CDC* pDC)

{

  CPen aPen;

  if (!aPen.CreatePen(PS_SOLID,m_PenWidth,m_Color))

  {

        AfxMessageBox(_T("Не удалось создать перо!"),MB_OK);

        AfxAbort();

  }

  CPen* pOldPen=pDC->SelectObject(&aPen);

  pDC->MoveTo(m_StartPoint);

  pDC->LineTo(m_EndPoint);

  pDC->SelectObject(pOldPen);

}

11.  Добавьте в проект класс CRectangle аналогично, как CLine. Описание класса представлено ниже:

class CRectangle :

  public CElement

{

public:

  CRectangle(void);

  ~CRectangle(void);

  virtual void Draw(CDC* pDC);//Функция отображения линии

  CRectangle (const CPoint& start,const CPoint& end,COLORREF aColor);//конструктор объекта прямоугольник

};

12. Реализуйте конструктор класса CRectangle:

CRectangle::CRectangle(const CPoint& start,const CPoint& end,COLORREF aColor)

{

  m_PenWidth=1;

  m_Color=aColor;

  //Определение описывающего прямоугольника

  m_EnclosingRect=CRect(start,end);

  m_EnclosingRect.NormalizeRect();

}

13. Напишите программный код метода Draw() класса CRectangle. Будем рисовать только контур прямоугольника, поэтому в качестве кисти будем использовать стандартную кисть NULL_ BRUSH. Ниже представлен код:

void CRectangle::Draw(CDC* pDC)

{

  CPen aPen;

  if (!aPen.CreatePen(PS_SOLID,m_PenWidth,m_Color))

  {

        AfxMessageBox(_T("Не удалось создать перо!"),MB_OK);

        AfxAbort();

  }

  CPen* pOldPen=pDC->SelectObject(&aPen);

  CBrush* pOldBrush=(CBrush*)pDC->SelectStockObject(NULL_BRUSH);

  pDC->Rectangle(m_EnclosingRect);

  pDC->SelectObject(pOldPen);

  pDC->SelectObject(pOldBrush);

}

14. Добавьте в проект класс CCircle, аналогично, как класс CRectangle в пункте 11.

15. Напишите конструктор класса CCircle, как приведено ниже:

CCircle::CCircle (const CPoint& start,const CPoint& end,COLORREF aColor)

{

  long radius=static_cast<long>(sqrt(static_cast<double>((end.x-start.x)*(end.x-start.x)+(end.y-start.y)*(end.y-start.y))));

  m_EnclosingRect=CRect(start.x-radius,start.y-radius,start.x+radius,start.y+radius);

  m_EnclosingRect.NormalizeRect();

  m_Color=aColor;

  m_PenWidth=1;

}

16. Для использования функции sqrt() необходимо в файл Element. cpp библиотеку cmath.

17. Реализуйте код рисования окружности для класса CCircle:

void CCircle::Draw(CDC* pDC)

{

CPen aPen;

  if (!aPen.CreatePen(PS_SOLID,m_PenWidth,m_Color))

  {

        AfxMessageBox(_T("Не удалось создать перо!"),MB_OK);

        AfxAbort();

  }

  CPen* pOldPen=pDC->SelectObject(&aPen);

  CBrush* pOldBrush=(CBrush*)pDC->SelectStockObject(NULL_BRUSH);

  pDC->Ellipse(m_EnclosingRect);//рисование окружности

  pDC->SelectObject(pOldPen);

  pDC->SelectObject(pOldBrush);

}

18. Добавьте в проект класс CCurve:

class CCurve : public CElement

{

public:

CCurve(void);

~CCurve(void);

virtual void Draw(CDC* pDC);//Функция отображения кривой

CCurve (const CPoint& first,const CPoint& second,COLORREF aColor);//конструктор объекта кривой

void AddSegment(const CPoint& point);//добавить сегмент кривой

protected:

std::vector<CPoint> m_Points;//множество точек, определяющих кривую

};

19. Подключите к файлу Element. h библиотеку vector.

20. Добавьте определение конструктора класса CCurve:

CCurve::CCurve (const CPoint& first,const CPoint& second,COLORREF aColor)

{

  m_Points.push_back(first);

  m_Points.push_back(second);

  m_EnclosingRect=CRect(min(first.x,second.x),

                                          min(first.y,second.y),

                                          max(first.x,second.x),

                                          max(first.y,second.y));

  m_Color=aColor;

  m_PenWidth=1;

}

21. Напишите метод прорисовки кривой класса CCurve:

void CCurve::Draw(CDC* pDC)

{

  CPen aPen;

  if (!aPen.CreatePen(PS_SOLID,m_PenWidth,m_Color))

  {

        AfxMessageBox(_T("Не удалось создать перо!"),MB_OK);

        AfxAbort();

  }

  CPen* pOldPen=pDC->SelectObject(&aPen);

  pDC->MoveTo(m_Points[0]);

  for (size_t i=1;i<m_Points.size();++i)

        pDC->LineTo(m_Points[i]);

  pDC->SelectObject(pOldPen);      

}

22. Добавьте метод добавления новой точки к кривой:

void CCurve::AddSegment(const CPoint& point)

{

  m_Points.push_back(point);

  m_EnclosingRect=CRect(min(point.x,m_EnclosingRect.left),

                             min(point.y,m_EnclosingRect.top),

                             max(point.x,m_EnclosingRect.right),

                             min(point.y,m_EnclosingRect.bottom));

}

23. Добавьте в класс документа методы, которые позволяют получить тип выбранного пользователем элемент и цвет пера, которые были определены в работе №4:

unsigned int Cmfc2Doc::GetElementType(void)

{

  return m_Element;

}

 

COLORREF Cmfc2Doc::GetColorElement(void)

{

  return m_Color;

}

24. Добавьте метод CreateElement в класс представления:

CElement* Cmfc2View::CreateElement(void) const

{

  Cmfc2Doc* pDoc=GetDocument();

  ASSERT_VALID(pDoc);

  switch (pDoc->GetElementType()){

  case RECTANGLE:

        return new CRectangle(m_FirstPoint,m_SecondPoint,pDoc->GetColorElement);

  case LINE:

        return new CLine(m_FirstPoint,m_SecondPoint,pDoc->GetColorElement());

  case CIRCLE:

        return new CCircle(m_FirstPoint,m_SecondPoint,pDoc->GetColorElement());

  case CURVE:

        return new CCurve(m_FirstPoint,m_SecondPoint,pDoc->GetColorElement());

  default:

        AfxMessageBox(_T("Неверный код элемента"),MB_OK);

        AfxAbort();

        return nullptr;

  }

  return NULL;

}

25. В файл Cmfc2View.h включите библиотеку Element.h.

26. Добавьте в класс представления переменную m_FirstPoint и m_SecondPoint типа CPoint и инициализируйте их в конструкторе класса значением CPoint(0,0).

27. Добавьте в класс представления указатель m_ pTempElement и инициализируйте его в конструкторе класса значением nullptr.

28. Создайте обработчик сообщения нажатия левой кнопки мыши в классе представления. Для этого в обозревателе классов выделите Cmfc2 View и в окне свойств нажмите кнопку «Сообщения». Найдите сообщение WM_ LBUTTON_ DOWN, нажмите на стрелку и выберите пункт «Add».

Рисунок 6.3 –Создание обработчика события мыши

 

29. В обработчике события нажатия ЛК мыши сохраните координаты:

void Cmfc2View::OnLButtonDown(UINT nFlags, CPoint point)

{

        m_FirstPoint=point;

}

30. Добавьте обработчик события перемещения мыши в классе представления:

void Cmfc2View::OnMouseMove(UINT nFlags, CPoint point)

{

  // TODO: добавьте свой код обработчика сообщений или вызов стандартного

  CClientDC aDC(this);//контекст устройства для данного представления

  if (nFlags&&MK_LBUTTON)//проверить, что нажата левая кнопка

  {

        m_SecondPoint=point;//сохранить координаты мыши

        if (m_pTempElement)

        {

               if (CURVE==GetDocument()->GetElementType())//если это кривая

               {

                      static_cast<CCurve*>(m_pTempElement)->AddSegment(m_SecondPoint);

                      m_pTempElement->Draw(&aDC);

                      return;

               }

//перерисовываем старый элемент, чтобы он исчез

               aDC.SetROP2(R2_NOTXORPEN);

               m_pTempElement->Draw(&aDC);

               delete m_pTempElement;

               m_pTempElement=nullptr;

        }

        m_pTempElement=CreateElement();//создать новый элемент

        m_pTempElement->Draw(&aDC);//нарисовать элемент

  }

}

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

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

{

  // TODO: добавьте свой код обработчика сообщений или вызов стандартного

  if (m_pTempElement)

  {

        delete m_pTempElement;

        m_pTempElement=nullptr;

  }

32. Для того чтобы обрабатывать сообщения мыши при выходе за пределы клиентской области добавьте в обработчике следующие строчки:

void Cmfc2View::OnLButtonDown(UINT nFlags, CPoint point)

{

  m_FirstPoint=point;

  SetCapture();//перехватывать все последующие сообщения мыши

}

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

{

  if (this==GetCapture())


Дата добавления: 2019-09-13; просмотров: 337; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!