Режимы отображения координат
Теперь покажем, как с помощью Studio .NET следует определять в классе собственные версии виртуальных функций. Мы собираемся однократно (при открытии окна) преобразовать "мировые" координаты в логические и запомнить их. Это удобно сделать внутри виртуальной функции OnlnitialUpdate, которая унаследована от класса cview. Она вызывается каркасом приложения в тот момент, когда окно еще не появилось на экране, но уже существует его Windows-описатель (HWND) и объект класса CMyView прикреплен (attached) к окну. Напомним также, что документ имеет и поддерживает динамический список всех своих представлений.
- В окне Class View поставьте курсор на имя класса CMyView и щелкните правой клавишей мыши.
- Перейдите в окно Properties, щелкнув вкладку, с помощью подсказок отыщите на панели инструментов именно этого окна кнопку Overrides и нажмите ее.
- Появится длинный список виртуальных функций родительских классов, которые можно переопределить в классе ему view. Найдите в нем функцию OnlnitialUpdate и выберите в правой половине таблицы действие <Add>.
Результат ищите в конце файла MyView.cpp. Внесите изменения в тело функции:
void CMyView::OnlnitialUpdate() { CView::OnlnitialUpdate(); // Создаем ссылку на контейнер World-координат точек VECPTSS pts = GetDocument() › m_Points; UINT size = pts.size (); //====== Задаем размер контейнера логических точек m_Points .resize (size); for (UINT i=0; i < size; m_Points[i] = (pts[i] * m_nLogZoom).Tolnt (); }
Здесь мы добываем из документа World-координаты объекта, умножаем их на коэффициент m_nLogZoom и преобразуем к целому типу. Обратите внимание на использование операций и методов вновь созданного класса CDPoint и на то, что переменная pts создана и инициализирована как ссылка на контейнер точек документа. Теперь осталось изменить коды для перерисовки представления так, чтобы воспользоваться техникой масштабирования, которую мы обсудили в начале главы:
void CMyView::OnDraw(CDC* pDC) { CMyDoc* pDoc = GetDocument (); ASSERT_VALID(pDoc); //====== Узнаем размер контейнера точек UINT nPoints = m_Points.size (); if (! nPoints) // Уходим, если он пуст return; // Сохраняем текущее состояние контекста pDC › SaveDC(); // Создаем перо Windows для прорисовки контура CPen pen (PS_SOLID,2,RGB(0, 96.0)); //====== Выбираем его в контекст устройства pDC › SelectObject (spen); // Создаем кисть Windows для заливки внутренности CBrush brush (RGB (240, 255, 250)); pDC › SelectObject (Sbrush); //====== Задаем режим преобразования координат pDC › SetMapMode(MM_ISOTROPIC); //====== Сдвиг в логической системе pDC › SetWindowOrg(0.0); //====== Сдвиг в физической системе pDC › SetViewportOrg (m_szView.cx/2, m_szView. су/2); //====== Знаменатель коэффициента растяжения pDC › SetWindowExt (3*m_nLogZoom, 3*m_nLogZoora); //====== Числитель коэффициента растяжения pDC › SetViewportExt (m_szView.cx, – m_szView.cy); //====== Изображаем полигон pDC › Polygon (Sra_Points [0], nPoints); // Восстанавливаем контекст (предыдущие инструменты GDI) pDC › RestoreDC (-1); }
Коэффициент 3 в параметрах SetWindowExt моделирует ситуацию, когда лист ватмана в 3 раза превышает размер детали, на нем изображенной. Знак минус в параметре SetViewportExt позволяет компенсировать изменение направления оси Y при переходе из Page space в Device space. При рисовании мы используем логические (Page) координаты, которые хранятся в классе CMyView.