Режимы отображения координат
При использовании контейнера объектов класса полезно декларировать новый тип данных:
typedef vector<CDPoint, allocator<CDPoint> > VECPTS;
Вставьте эту строку сразу после объявления класса CDPoint. Данное объявление позволяет просто создавать множество контейнеров для хранения точек с вещественными координатами. Представим, что документ должен хранить контуры нескольких деталей сложной конструкции. Тогда каждая деталь конструкции может быть объявлена объектом типа VECPTS, то есть она является контейнером, содержащим координаты точек своего контура.
Кроме трех конструкторов для удобства пользования в классе CDPoint заданы правила сложения и вычитания точек. Метод Tolnt позволяет создать стандартную точку Windows (CPoint) из нашей вещественной точки. Операция умножения точки на целое число без знака (CDPoint operator* (UINT n);) позволяет увеличивать координаты объекта, что мы используем при переходе из World – в Page-пространство. Операция вычисления нормы вектора, начало которого находится в точке (0.0), а конец в данной точке, полезна при оценке степени близости двух точек. В одном из следующих уроков она нам пригодится. Тело конструктора документа можно упростить, так как теперь он помнит реальные координаты объекта и необходимость преобразовывать координаты в пространство Page исчезла. Это преобразование мы сделаем в классе CMyView:
CMyDoc::CMyDoc() { // ====== Вспомогательные переменные double pi = 4. * atan(l.), //====== Углы al = pi / 10., a2 = 3. * a1, //===== 2 характерные точки xl = cos(al), yl = sin(al), x2 = cos(a2), y2 = sin(a2); //==== Вещественные (World) координаты углов звезды m_Points.push_back(CDPoint(0., 1.)); m_Points.push_back(CDPoint(-x2, – y2)); m_Points.push_back(CDPoint(xl, yl)); m_Points.push_back(CDPoint(-xl, yl)); m_Points.push_back(CDPoint(x2, – y2)); }
Масштабирование изображения можно упростить, если следить за текущими размерами клиентской области окна. При изменении пользователем размеров окна-рамки в момент отпускания кнопки мыши система посылает приложению сообщение WM_SIZE, на которое должен среагировать класс CMyView и запомнить в переменной m_szView новые размеры.
Сейчас мы введем в состав CMyView новую функцию отклика, которая будет вызываться в ответ на приход сообщения WM_SIZE. Она должна иметь имя OnSize (так устроена MFC) и иметь особый спецификатор afx_msg, который невидим компилятором (препроцессор заменит его пустым местом), но нужен инструментам Studio .NET. Спецификатор несет информацию о том, что функция OnSize особая – она является эффективно реализованным обработчиком сообщения (message handler). В Studio .NET процесс создания функций-обработчиков и виртуальных функций сильно изменен. Теперь это делается не с помощью ее инструмента ClassWizard, следы которого однако присутствуют в студии, а в окне Properties.
- Выделите имя класса CMyView в окне Class View и перейдите на страницу Properties, выбрав соответствующую вкладку.
- Обратите внимание на панель инструментов окна Properties. Она динамически изменяется в зависимости от выбора (selection) в других окнах. Сейчас на ней должна быть кнопка с подсказкой Messages. Нажмите эту кнопку.
- В появившемся списке сообщений найдите сообщение WM_S IZE. В правой ячейке (типа Combo box) таблицы выберите <Add> OnSize.
- Вновь перейдите в окно Class View, найдите новую функцию-обработчик OnSize в составе класса CMyView и сделайте на ней двойной щелчок.
- Фокус ввода переходит в окно редактора текста для файла MyView.cpp. Введите изменения так, чтобы функция приобрела вид:
void CMyView::OnSize(UINT nType, int ex, int cy) { //========== Вызов родительской версии CView::OnSize(nType, ex, cy); if (cx==0 || cy==0) return; //========= Запоминаем размеры окна представления m_szView = CSize (ex, су); };
Проверка if (cx==0…) необходима потому, что каркас приложения вызывает OnSize несколько раз и иногда с нулевыми размерами. Обратите внимание на то, что мастер вставок добавил также и прототип (объявление) функции обработки в интерфейс класса CMyView (см. файл MyView.h):
public: afx_msg void OnSize(UINT nType, int ex, int cy);