Иллюстрированный самоучитель по Visual Studio .NET

Режимы отображения координат

Масштабирование изображения

Зададимся целью внести изменения в приложение My, которое мы создали в предыдущей главе, таким образом, чтобы изображение геометрической фигуры всегда было в центре окна и следило за изменением размеров окна приложения, меняясь пропорционально. Напомним, что фигурой является многоугольник с произвольным количеством вершин, и он выводится в контекст устройства Windows с помощью объекта класса CDC. Для того чтобы упростить процесс слежения за размерами окна представления, введем в число членов класса CMyView новую переменную, которая будет хранить текущие размеры окна.

  1. Вызовите контекстное меню над именем класса CMyView в окне Class View и выберите команду Add › Add Variable.
  2. Заполните поля окна мастера так, чтобы он создал private-переменную m_s zView типа csize.
  3. Убедитесь в том, что мастер Add Variable выполнил свою работу. В окне Class View вы должны увидеть ее в числе данных класса.
  4. Повторите эти же действия и введите в состав CMyView private переменную UINT m_nLogZoom, в которой мы будем хранить коэффициент увеличения, используемый при переходе из пространства World в пространство Page.
  5. В пространстве 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); } };
Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.