Конструкторы и операции
Метод GetRect получает на входе ссылки на две характерные точки прямоугольника, обрамляющего весь полигон, вычисляет координаты этих точек и возвращает их с помощью механизма передачи ссылкой:
void CPolygon::GetRect(CDPointS ptLT, CDPointi ptRB) { m_ptLT = m_ptRB = CDPoint(0., 0.); //====== Если полигон содержит точки контура UINT n = ra_Points.size(); if (n > 0) { //====== Пробег по всем его точкам for (UINT 1=0; i<n; i++) { //====== Поиск и запоминание экстремумов double х = m_Points[i].x, у = m_Points[i].у; if (x < m_ptLT.x) m_ptLT.x = x; else if (x > m_ptRB.x) m_ptRB.x = m_Points[i].x; if (y > m_ptLT.y) ra_ptLT.y = y; else if (y < m_ptRB.y) m_ptRB.y = y; } } //====== Возвращаем найденные координаты (ссылками) ptLT = m_ptLT; ptRB = m_ptRB; }
Метод сериализации данных полигона, приведенный ниже, мог бы быть более компактным, если бы для хранения точек полигона мы воспользовались бы одним из шаблонов семейства классов Collection библиотеки MFC. В эти классы уже встроена возможность сериализации. Но у нас на вооружении шаблон классов vector из другой библиотеки STL, так как он обладает рядом других привлекательных черт. За это приходится платить несколькими лишними строками кода, в котором все точки контейнера либо помещаются в архив, либо выбираются из него:
void CPolygon::Serialize (CArchiveS ar) { //====== Если идет запись в архив, if (ar. IsStoring() } { //=== то последовательно переносим туда все данные m << m_nPenWidth << m_PenColor << m_BrushColor << m_Points .size () << m_ptLT.x << m_ptLT.y << m_ptRB.x << m_ptRB.y; for (UINT i=0; i <m_Points .size 0; m << m_Points [i].x << m_Points [i] .y; } else { //=== При чтении из архива меняем направление обмена UINT size; m >> m_nPenWidth >> m_PenColor >> m_BrushColor >> size >> m_ptLT.x >> m_ptLT.y >> m_ptRB.x >> m_ptRB.y; //====== Заново создаем контейнер точек полигона m_Points .clear (); while (size--) { double x, y; m >> x >> y; m_Points .oush back (CDPoint (x, v)); } } }
Ниже приведена функция рисования полигона в переданный ей в качестве параметра контекст устройства. Второй параметр является флагом, который задает способ заливки полигона. В операциях визуального редактирования, которое мы введем позже, полигон должен временно терять свой цвет, для того чтобы не было мелькания при частых перерисовках.
Напомним, что полигон хранит World-координаты всех своих точек в контейнере m_Points. Переход к Page-координатам производится с помощью функции MapToLogPt, которую мы еще должны разработать и поместить в класс документа. Двигаясь далее по коду функции Draw, мы видим, как объект настраивает контекст устройства с помощью своих личных атрибутов и изображает себя в этом контексте:
void CPolygon::Draw (CDC *pDC, bool bContour) { //====== Размер контейнера World-координат точек UINT nPoints = m_Points.size(); if (!nPoints) return; //====== Временный массив логических координат точек CPoint *pts = new CPoint[nPoints]; //====== Преобразование координат for (UINT i=0; KnPoints; i++) pts[i] = m_pDoc › MapToLogPt(m_Points[i]); pDC › SaveDC(); CPen pen (PS_SOLID,m_nPenWidth,m_PenColor); pDC › SelectObject(Spen); CBrush brush (bContour? GetSysColor(COLOR_WINDOW): m_BrushColor); pDC › SelectObject(ibrush); //====== Полигон изображается в предварительно //====== подготовленном контексте устройства pDC › Polygon(pts, nPoints); //====== Освобождаем массив delete [] pts; pDC › RestoreDC(-1); }