Режимы отображения координат
Масштабирование изображения
Зададимся целью внести изменения в приложение My, которое мы создали в предыдущей главе, таким образом, чтобы изображение геометрической фигуры всегда было в центре окна и следило за изменением размеров окна приложения, меняясь пропорционально. Напомним, что фигурой является многоугольник с произвольным количеством вершин, и он выводится в контекст устройства Windows с помощью объекта класса CDC. Для того чтобы упростить процесс слежения за размерами окна представления, введем в число членов класса CMyView новую переменную, которая будет хранить текущие размеры окна.
- Вызовите контекстное меню над именем класса CMyView в окне Class View и выберите команду Add › Add Variable.
- Заполните поля окна мастера так, чтобы он создал private-переменную m_s zView типа csize.
- Убедитесь в том, что мастер Add Variable выполнил свою работу. В окне Class View вы должны увидеть ее в числе данных класса.
- Повторите эти же действия и введите в состав CMyView private переменную UINT m_nLogZoom, в которой мы будем хранить коэффициент увеличения, используемый при переходе из пространства World в пространство Page.
- В пространстве Page мы увеличим изображение в 100 раз. Измените уже созданный в конструкторе CMyView инициализатор m_nLogZoom (0) на m_nLogZoom (100).
Примечание
Если вы помните (об этом я уже говорил в связи с конструктором документа), наш многоугольник "в миру" задан вещественными координатами и имеет размах в 2 единицы, так как мы вписали его в окружность единичного радиуса, то есть диаметром в 2 единицы. Там же мы преобразовали все координаты в логическую систему, увеличив размеры многоугольника в 100 раз и перевернув его (так как ось Y экрана направлена вниз). Кроме того, мы сдвинули изображение вправо и вниз, чтобы попасть в центр "листа ватмана". Логические координаты (уже целого типа) мы занесли в массив m_Points, который использован в функции OnDraw класса представления при изображении многоугольника. Теперь надо изменить ситуацию. Обычно документ хранит истинные ("мировые") координаты объектов, а класс представления преобразовывает их в логические и изображает в физическом устройстве с помощью рассмотренных преобразований. Так делают, потому что пользователя не интересуют логические (Page) координаты. Он должен видеть и иметь возможность редактировать реальные (World) координаты объекта.
Чтобы реализовать указанный подход, надо заменить в классе документа массив целых координат на массив вещественных, а в классе CMyView создать еще один массив, но уже целых координат. Используя уже знакомую технику, введите в состав класса CMyView private-переменную:
vector<CPoint> m_Points;
Ее имя совпадает с именем массива координат в документе, но это не помеха, если используешь ООП. Классы ограничивают область действия имен, скрывая их. В интерфейсе класса документа (файл MyDoc.h) замените объявление:
vector<CPoint> m_Points;
На:
VECPTS m_Points;
Этой заменой мы оставили для контейнера то же имя, но изменили тип его элементов. Тип данных VECPTS – вектор точек с вещественными (World) координатами – пока не определен, но мы собираемся его декларировать и определить для того, чтобы было удобно хранить реальные координаты объекта. Для начала создадим свой собственный класс CDPoint, инкапсулирующий функциональность точки с вещественными координатами. Вставьте в начало файла MyDoc.h после директивы препроцессора #pragma once, но до объявления класса CMyDoc декларацию нового класса:
//====== Новый класс "Вещественная точка" class CDPoint { public: double x; double у; // Вещественные координаты //====== Конструктор по умолчанию CDPoint() { х=0.; у=0.; } //====== Конструктор копирования CDPoint(const CDPointS pt) { x = pt.x; y = pt.y; } //====== Конструктор с параметрами CDPoint(double xx, double yy) { x = x x; у = yy; } //====== Операция умножения (увеличение в п раз) CDPoint operator* (UINT n) { return CDPoint (x*n, y*n); } //====== Операция присваивания CDPointS operator=(const CDPointS pt) { x = pt.x; у = pt.y; return *this; // Возвращаем свой объект } //====== Операция сложения двух точек CDPoint operator*(CDPointS pt) { return CDPoint(x + pt.x, у + pt.y); } //====== Операция вычитания двух точек CDPoint operator- (CDPointS pt) { return CDPoint(x – pt.x, у – pt.y); } // Метод приведения к типу CPoint (целая точка) CPoint Tolnt() { return CPoint(int(x),int(у)); } //====== Операция сложения с записью результата void operator +=(CDPointS pt) { x += pt.x; у += pt.y; } //====== Операция вычитания с записью результата void operator – =(CDPoint& pt) { x – pt.x; у – = pt.y; } // Операция вычисления нормы вектора, заданного точкой double operator!() { return fabs(x) + fabs(y); } };