C++ C++ C# C# ASP.NET Security ASP.NET Security ASM ASM Скачать Скачать Поиск Поиск Хостинг Хостинг  
  Программа для работы с LPT портом...
Язык: .NET — ©Alexey...
  "ASP.NET Atlas" – AJAX в исполнении Micro...
Язык: .NET — ©legigor@mail.ru...
  "Невытесняющая" Многопоточность...
Язык: C/C++ — ©...
  01.05.2010 — Update World C++: Сборник GPL QT исходников
  15.12.2007 — Весь сайт целиком можно загрузить по ссылкам из раздела Скачать
Хостинг:
Windows 2003, ASP.NET 2.0
бесплатный и от 80 руб./мес


   Отправить письмо
Кулабухов Артем, Беларусь




 Режимы отображения координат / Рисование / Графика

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

Мы хотим добиться того, чтобы приложение Мар позволяло исследовать различные режимы отображения логической системы координат в физическую при «рисовании» в клиентской области окна. Вообще Win32 API использует четыре координатных пространства (space): World space, Page space, Device space и Physical Device space. Однако большая часть документации и книг по MFC оперирует только двумя устаревшими терминами: логическая и физическая системы координат. Мы же будем пользоваться понятием «логическая система координат», имея в виду Page space.

Заметьте, что и World space, и Page space измеряют плоскую область, размах которой по обеим координатам равняется 232 (логических) единиц, то есть более 4 млрд единиц. Page space работает совместно, с Device space, чтобы обеспечить приложение единицами, не зависящими от типа физического устройства, такими как миллиметры и дюймы (inches). Конечным координатным пространством, Physical Device space, обычно является клиентская область окна приложения, или весь экран монитора, или страница бумаги принтера или плоттера. Размеры области физического устройства изменяются в зависимости от марки, технологии и т.д. Чтобы верно передать детали изображения (созданного в логической системе) в физическое устройство, система преобразовывает их путем отображения (mapping) прямоугольной области из одного координатного пространства в другое. При копировании каждой точки прямоугольной области из одного пространства в другое Windows применяет алгоритм трансформации, который в конечном счете изменяет размеры, ориентацию и форму всего объекта.

Анализ соответствия между логической системой координат (в которой работают все функции рисования) и физической системой координат (которая, например, используется в клиентской области окна) будем проводить, наблюдая за трансформацией прямоугольника, эллипса и прямой линии при изменении как самих режимов отображения координат ( mapping mode), так и их атрибутов. Вы помните, что рисование производится в логической структуре, называемой контекстом устройства. Этим достигается независимость рисунка от конкретного устройства, в которое будет осуществлен вывод изображения. Функциональность контекста устройства поддерживается классом CDC или одним из его потомков. Для выбора режима отображения используются методы этого класса:

  • SetMapMode – задание режима отображения координат;
  • SetWindowOrg – задание выделенной точки (начала отображения) в логической системе координат;
  • SetViewportOrg – задание выделенной точки (начала отображения) в физической системе координат;
  • SetWindowExt – характеристика протяженности окна вдоль двух логических координат;
  • SetViewportExt – характеристика протяженности окна вдоль двух физических координат.

Восемь существующих режимов отображения координат задаются с помощью символьных констант, определенных в файле Wingdi.h.

   // Одна логическая единица соответствует одному пикселу
  #define MM_TEXT        1
     // Одна логическая единица соответствует 0,1 мм
  #define MM_LOMETRIC    2
     // Одна логическая единица соответствует 0,01 мм
  #define MM_HIMETRIC    3
     // Одна логическая единица соответствует 0,01 дюйма
  #define MM_LOENGLISH   4
     // Одна логическая единица соответствует 0,001 дюйма
  #define MM_HIENGLISH   5
     // Одна логическая единица соответствует 1/1440 дюйма
  #define MM_TWIPS       6
     // Преобразование по формуле. Растяжение по осям одинаково
  #define MM_ISOTROPIC   7
     // Преобразование по формуле. Растяжение по осям различно
  #define MM_ANISOTROPIC 8

В двух последних режимах преобразование координат из Page-Space в Device-Space (из логической системы координат в физическую) выполняется в соответствии с формулами, которые приведены ниже. При этом используются следующие обозначения:

  • Viewport – область вывода, задаваемая физическими координатами;
  • Window – окно, задаваемое логическими координатами.

Выделенные точки Window и Viewport совмещаются, а изображение растягивается или сжимается так, что горизонтальная координата каждой точки изображения при выводе в физическое устройство вычисляется по формуле линейного преобразования:

DX – аппаратная (device) или физическая Х-координата точки;

LX – логическая (logical) Х-координата точки;

VEX – протяженность области вывода, задаваемая SetViewportExt;

WEX – протяженность окна, задаваемая SetWindowExt;

VOX – Х-координата выделенной точки области вывода (SetViewportOrg);

WOX – Х-координата выделенной точки окна (SetWindowOrg).

Аналогичная формула справедлива для Y-координаты точки. Например, если в режиме MM_ANISOTROPIC заданы значения:

     // Выделенная точка в логическом окне
  pDC->SetWindowOrg(300, 0);
       // Выделенная точка в физической системе
  pDC->SetViewportOrg(200, 200);
       //Протяженность логического окна
  pDC->SetWindowExt(100, 100);
       // Протяженность физической области
  pDC->SetViewportExt(50, -200);

то логические координаты точек CPoint pl(0, 0), p2(100, 100); преобразуются в аппаратные (физические) pl(50, 200) и pl2(100, 0). Проверим первую координату подстановкой в формулу:

Таким образом, если мы хотим увеличить или уменьшить изображение, то нужно изменить следующие величины:

В режиме MM_ISOTROPIC система обеспечивает одинаковое расширение (сжатие) по обеим осям, поэтому результат вычислений по приведенным формулам зависит от соотношения величин коэффициентов растяжения (сжатия). Видно, что режим MM_ANISOTROPIC обеспечивает наибольшую свободу и гибкость в преобразовании координат. Числитель и знаменатель в формулах для коэффициентов растяжения (сжатия) задаются по отдельности с помощью методов класса CDC. Метод SetViewportExt задает числитель обоих отношений, следовательно, определяет свойства физического устройства, а метод SetWindowExt задает знаменатель, то есть задает свойства логической системы координат. Имена функций вводят нас в заблуждение, так как на самом деле эти функции ничего не задают и не определяют. Работая в паре, они дают способ задания двух вещественных коэффициентов растяжения (сжатия) путем задания четырех целых чисел. Параметры функций должны быть целыми или объектами класса CSize (которые тоже создаются из двух целых). Значительно проще было бы задать два вещественных числа и использовать их в качестве коэффициентов. Объяснение наблюдаемой реальности, видимо, кроется в истории разработки функций API.

При выводе изображений мы хотим дать возможность пользователю выбрать любой из восьми режимов отображения координат. Кроме того, мы хотим иметь возможность изменения всех величин, управляющих отображением. Будем считать, что текущий режим отображения хранится в переменной int nMode. Пусть координаты начала и конца тестовой линии заданы в переменных ptSt, ptEn – объектах класса CPoint. Пусть эти точки определяют также координаты углов прямоугольника и координаты эллипса. Все указанные переменные следует вставить в число данных класса MyW и инициализировать их в конструкторе. Вставьте нижеследующий код в private-секцию класса:

UINT PenSize;            // Толщина линии
  COLORREF color;          // Цвет
        // Характерные точки:
  CPoint wOrg, vOrg;       // выбранные
  CPoint ptCur;            // текущая
  CPoint ptSt, ptEn;       // координаты фигур
  CSize wExt, vExt;        // Характерные размеры
  CPen pen;                // Объект класса, управляющего пером Windows
  int nMode;               // Режим отображения координат

Следующие начальные присвоения вставьте в тело конструктора класса MyW:

PenSize = 2;             // Толщина пера
  color = RGB(0, 0, 255);  // Цвет, образованный из компонентов
  pen.CreatePen(PS_SOLID, PenSize, color); // Создаем перо
  wOrg.x = 0;    wOrg.y = 0;   // Выбранная точка окна
  vOrg.x = 20;   vOrg.y = 20;  // Выбранная точка области вывода
  wExt.cx = 10;  wExt.cy = 10; // Протяженность окна
  vExt.cx = 10;  vExt.cy = 10; // Протяженность области вывода
  ptCur.x = 0;   ptCur.y = 0;  // Текущая точка
  ptSt.x = 0;    ptSt.y = 0;   // Начальная точка для изображаемых фигур
  ptEn.x = 100;  ptEn.y = 100; // Конечная точка для этих фигур
  nMode = MM_TEXT;             // Начальный режим отображения

Функция CreatePen динамически создает перо Windows (структуру типа HPEN), захватывая память для лимитированных ресурсов Windows. Из этого следует, что после использования пера следует освободить память вызовом функции DeleteObject. Эта функция является методом класса CGdiObject, который является базовым для всех шести классов, инкапсулирующих функциональность GDI-объектов (CPen, CBrush, CFont, CPalette, CBitmap, CRgn). Объекты GDI используются как инструменты для рисования. Выводя текст, мы тоже рисуем его с помощью объекта класса CFont. До сих пор нас удовлетворяли инструменты, предоставляемые системой (каркасом приложения) по умолчанию, однако теперь мы берем управление ими в свои руки.

Существуют две тактики использования всех GDI-объектов. Первую можно назвать расточительной, а вторую – экономной. Важно представлять, что с объектом GDI связаны две сущности языка С++; MFC-класс (например CPen) и Windows-структура (например HPEN). При создании объекта (например CreatePen) структура прикрепляется к классу. Первая тактика после использования объекта безжалостно уничтожает как объект класса, так и прикрепленную структуру. Вторая – создает логический объект (например, структуру LOGPEN) и прикрепляет ее к объекту класса MFC (функция CGdiObject::Attach). После использования мы не уничтожаем структуру, а открепляем ее (функция CGdiObject::Detach), изменяем ее поля (атрибуты пера), а затем снова прикрепляем к объекту класса MFC (например CPen). Обе тактики следует иметь в своем арсенале. Для обеих тактик справедливо, что после создания инструмента рисования надо выбрать его в контекст устройства (функцией CDC::SelectObject), использовать в функциях рисования, таких как LineTo или TextOut, и при ненадобности освободить память функцией DeleteObject.

Мы, следуя первой тактике, должны создать контекст устройства для рисования в клиентской области окна, выбрать режим отображения координат, задать его атрибуты, выбрать инструмент для рисования (перо) и использовать его для вывода тестовых фигур. Все эти действия выполняются в функции OnPaint – реакции на сообщение WM_PAINT. Введите новую версию ее тела:

void MyW::OnPaint()
  {
     CPaintDC *pDC = new CPaintDC(this);

     pDC->SetMapMode(nMode);         // Режим отображения

               // Установка характерных точек и размеров
     pDC->SetWindowOrg(wOrg);
     pDC->SetViewportOrg(vOrg);
     pDC->SetWindowExt(wExt);
     pDC->SetViewportExt(vExt);
     pDC->SelectObject(pen);            // Выбор пера для рисования

               // Прямоугольник, в который вписан эллипс
     CRect r(ptSt, ptEn);
     pDC->Rectangle(r);                 // Вывод прямоугольника
     pDC->Ellipse(r);                   // Вывод эллипса
     pDC->MoveTo(ptSt);                 // Вывод начальной точки линии
     pDC->LineTo(ptEn);                 // Вывод линии
     delete pDC;             // Освобождаем контекст устройства
  }

Запустите приложение. Вы должны увидеть окно с синими прямоугольником, эллипсом и линией, смещенными на 20 пикселов по обеим координатам. Это изображение получено в режиме MM_TEXT, заданном в конструкторе класса MyW. С помощью мыши определите координаты начала и конца линии на экране (физические координаты) и объясните эти значения, связав их с координатами, заданным в конструкторе.