95 в двух томах Том I



Pdf просмотр
страница11/41
Дата27.11.2016
Размер4.32 Mb.
Просмотров7963
Скачиваний0
ТипРеферат
1   ...   7   8   9   10   11   12   13   14   ...   41
Направление увеличения
Режим
отображения
Логические
единицы
ось x



ось y
MM_TEXT
Пиксели вправо вниз
MM_LOMETRIC 0.1 мм вправо вверх
MM_HIMETRIC 0.01 мм вправо вверх
MM_LOENGLISH 0.01 дюйма вправо вверх
MM_HIENGLISH 0.001 дюйма вправо вверх
MM_TWIPS
*
1/1440 дюйма вправо вверх
MM_ISOTROPIC
Произвольные (x=y) выбирается выбирается
*
Слово "twip" производное от "twentieth of a point" — одна двадцатая часть точки. Точка, как единица измерения, равна примерно 1/72 дюйма, однако часто в графических системах таких как GDI, считается точно равной 1/72 дюйма. Twip — это 1/20 точки и, следовательно, 1/1440 дюйма.

101
Направление увеличения
Режим
отображения
Логические
единицы
ось x



ось y
MM_ANISOTROPIC
Произвольные (x!=y) выбирается выбирается
Вы можете устанавливать режим отображения, используя функцию:
SetMapMode(hdc, iMapMode);
Параметр iMapMode — это один из восьми идентификаторов режима отображения. Определить текущий режим отображения вы можете путем вызова: iMapMode = GetMapMode(hdc);
По умолчанию установлен режим MM_TEXT. В этом режиме отображения логические единицы эквивалентны физическим единицам, что позволяет нам (или заставляет нас) работать непосредственно в терминах пикселей. В следующем вызове функции TextOut

:
TextOut(hdc, 8, 16, szBuffer, iLength); текст начинается в точке, отстоящей на 8 пикселей слева и на 16 пикселей сверху от границы рабочей области.
Если установлен режим отображения MM_LOENGLISH, то логические единицы — это сотые доли дюйма:
SetMapMode(hdc, MM_LOENGLISH);
Теперь вызов функции TextOut может выглядеть так:
TextOut(hdc, 50, -100, szBuffer, iLength);
Текст начинается на расстоянии 0,5 дюйма от левого края и на расстоянии 1-го дюйма от верхнего края рабочей области. (Почему у координаты y стоит знак минус, станет понятно позже, когда режимы отображения будут рассматриваться более подробно.) Другие режимы отображения позволяют программе задавать координаты вывода в миллиметрах, размерах точки принтера или произвольных единицах.
Если вы чувствуете себя уверенно при работе с пикселями, то вам не нужно использовать другие, отличные от
MM_TEXT, режимы отображения. Если же вы хотите рисовать образы в реальных единицах измерения, таких как миллиметры или дюймы, то вы можете получить нужную вам информацию из функции GetDeviceCaps и осуществлять свое собственное масштабирование. Другие режимы отображения просто освобождают вас от этой рутинной работы.
Независимо от режима отображения все координаты, которые вы задаете в функциях Windows, должны быть знаковыми короткими целыми (signed short integer) числами в интервале от —32768 до 32767. Некоторые функции
Windows, использующие начальную и конечную точки прямоугольника, также требуют, чтобы ширина и высота прямоугольника были меньше чем 32767.
Координаты устройства (физические координаты) и логические координаты
Вы можете спросить: если использовать режим отображения MM_LOENGLISH, можно ли получать сообщения
WM_SIZE в терминах сотых долей дюйма? Конечно, нет. Windows продолжает использовать координаты устройства для всех сообщений (таких как WM_MOVE, WM_SIZE и WM_MOUSEMOVE), для всех функций, не принадлежащих GDI, и даже для некоторых функций GDI. Посмотрите на это с такой точки зрения: режим отображения — это атрибут контекста устройства, поэтому он начинает работать только тогда, когда вы используете функции GDI, требующие передачи им описателя контекста устройства. GetSystemMetrics — не является функцией GDI, следовательно, она будет продолжать возвращать размеры в координатах устройства, т. е. в пикселях. И хотя функция GetDeviceCaps — функция GDI и требует описателя контекста устройства, Windows продолжает возвращать единицы измерения устройства для индексов HORZRES и VERTRES, поскольку одна из задач этой функции — дать программе сведения о размерах устройства в пикселях.
Тем не менее, величины в структуре TEXTMETRIC, которую можно получить из функции GetTextMetrics, задаются в логических координатах. В режиме отображения MM_LOENGLISH функция GetTextMetrics возвращает информацию о ширине и высоте символов в сотых долях дюйма. Когда вы вызываете функцию GetTextMetrics для получения информации о ширине и высоте символов, режим отображения должен быть установлен таким, каким он будет, когда вы вызовите функцию рисования, использующую эти размеры. Поскольку в этой главе рассматриваются различные функции GDI, ваше внимание будет обращаться на то, какие координаты они используют — логические или физические. Все функции, которые мы рассматривали до сих пор, используют логические координаты, за исключением тех, которые определяют закрашивание пустот между точками и штрихами в линиях, и между штрихами в штриховых шаблонах. Работа этих функций не зависит от режима отображения.

102
Системы координат устройства
Windows преобразует логические координаты, заданные в функциях GDI, в координаты устройства. Перед тем, как мы рассмотрим логические системы координат, используемые в различных режимах отображения, давайте разберемся с системой координат устройства, которую Windows определяет для экрана дисплея. Хотя мы работали в основном с рабочей областью окна, Windows использует еще два других пространства координат устройства в разные моменты времени. Во всех системах координат устройства единицами всегда считаются пиксели. Значения горизонтальной координаты x возрастает слева направо, значения вертикальной координаты y — сверху вниз.
Когда мы работаем с экраном целиком, мы работаем в терминах "экранных координат." Левый верхний угол экрана — точка (0, 0). Экранные координаты используются в сообщениях WM_MOVE (для окон верхнего уровня, не дочерних) и в следующих функциях Windows: CreateWindow и MoveWindow (обе для не дочерних окон),
GetMessagePos, GetCursorPos, SetCursirPos, GetWindowRect, WindowFromPoint и SetBrushOrgEx. Эти функции, в основном, не имеют окна, ассоциированного с ними (например, две функции работы с курсором), или функции, которые должны переместить или найти окно на основе положения некоторой точки экрана. Если вы используете функцию CreateDC с параметром DISPLAY для получения контекста устройства всего экрана, то логические координаты, указанные в вызовах функций GDI, будут преобразованы в координаты устройства.
"Полные координаты окна" (whole-window coordinates) определяют окно программы целиком, включая заголовок, меню, полосы прокрутки и рамку. Для обычного окна точка (0, 0) — левый верхний угол рамки окна. Полные координаты окна редко используются в Windows, но если вы получите контекст устройства, используя функцию
GetWindowDC, то логические координаты в вызовах функций GDI будут преобразовываться в координаты всего окна.
Третья система координат устройства — это та, с которой мы работали больше всего, — система координат рабочей области окна. Точка (0, 0) — верхний левый угол рабочей области окна. Когда вы получаете контекст устройства, используя функции GetDC или BeginPaint, логические координаты в вызовах функций GDI преобразуются в координаты рабочей области окна.
Вы можете конвертировать координаты рабочей области окна в координаты экрана и наоборот, используя функции
ClientToScreen и ScreenToClient. Вы можете также получить местоположение и размеры окна целиком в экранных координатах, используя функцию GetWindowRect. Эти три функции предоставляют достаточно возможностей для любых преобразований координат.
Область вывода и окно
Режим отображения определяет, как Windows преобразует логические координаты, заданные в параметрах функций GDI, в координаты устройства, конкретная система координат которого зависит от того, какой функцией вы получили контекст устройства. Для дальнейшего рассмотрения режимов отображения нам необходимо определить некоторые дополнительные термины: Говорят, что режим отображения определяет преобразование "окна" (window) — логические координаты, в "область вывода" (viewport) — координаты устройства.
Использование слов "окно" и "область вывода" не совсем удачно. В других языках графического интерфейса "область вывода" часто определяется как "область отсечения" (clipping region). Мы использовали термин "окно", имея в виду область экрана, захваченную программой. Мы должны оставить в стороне наше предвзятое мнение об этих терминах на время обсуждения.
Область вывода описывается в терминах координат устройства (пикселях). Чаще всего область вывода — это то же самое, что и рабочая область, хотя область вывода может описываться также и в полных координатах окна или в координатах экрана, если вы получили контекст устройства из функций GetWindowDC или CreateDC. Точка (0, 0)
— левый верхний угол рабочей области (или окна целиком, или всего экрана). Значения координаты x возрастают слева направо, а значения координаты y — сверху вниз.
"Окно" описывается в терминах логических координат. Ими могут быть пиксели, миллиметры, дюймы или любые другие единицы, какие вы захотите. В вызовах функций GDI вы задаете логические координаты.
Для всех режимов отображения Windows преобразует оконные (логические) координаты в координаты области вывода (координаты устройства), используя следующие формулы:
xViewport = (xWindow — xWinOrg)
×
(xViewExt/xWinExt) + xViewOrg
yViewport = (yWindow — yWinOrg)
×
(yViewExt/yWinExt) + yViewOrg,
где (xWindow, yWindow) — логическая точка для преобразования, (xViewport, yViewport) — преобразованная точка в координатах устройства. Если координаты устройства — это координаты рабочей области или окна целиком, то Windows должна также преобразовать их в координаты экрана перед выводом объекта.
Эти формулы используют две точки, задающие начала координат (origin) окна и области вывода: (xWinOrg,
yWinOrg) — начало координат окна в логических координатах; (xViewOrg, yViewOrg) — начало координат области

103 вывода в координатах устройства. В контексте устройства, установленном по умолчанию, обе эти точки установлены в точку (0, 0), но они могут быть изменены. Эти формулы гарантируют, что точка с логическими координатами (xViewOrg, yViewOrg) всегда преобразуется в точку с физическими координатами (xViewOrg,
yViewOrg).
Эти формулы используют также две точки, определяющие "протяженность" (extent): (xWinExt, yWinExt) — протяженность окна в логических координатах; (xViewExt, yViewExt) — протяженность области вывода в координатах устройства. В большинстве режимов отображения протяженности определяются самими режимами и не могут быть изменены. Каждая протяженность сама по себе ничего не значит. Только отношение протяженности области вывода к протяженности окна является коэффициентом масштабирования при пересчете логических координат в координаты устройства. Протяженность может быть отрицательной. Это означает, что величина логической координаты x не обязательно должна возрастать при перемещении вправо, а величина логической координаты y — необязательно возрастать при движении вниз.
Windows может также преобразовывать координаты устройства (физические) в координаты окна (логические):
xWindow = (xViewport — xViewOrg)
×
(xWinExt/xViewExt) + xWinOrg
yWindow = (yViewport — yViewOrg)
×
(yWinExt/yViewExt) + yWinOrg
Windows имеет также две функции, которые позволяют вам в программе преобразовывать координаты устройства в логические координаты и логические координаты в координаты устройства. Следующая функция преобразует точки устройства в логические точки:
DPtoLP(hdc, pPoints, iNumber);
Переменная pPoints — это указатель на массив структур типа POINT, iNumber — число преобразуемых точек. Вы обнаружите, что эта функция очень полезна для преобразования размера рабочей области, полученного от функции GetClientRect (которая всегда оперирует с координатами устройства), в логические координаты:
GetClientRect(hwnd, &rect);
DPtoLP(hdc,(PPOINT) &rect, 2);
Следующая функция преобразует логические точки в физические точки:
LPtoDP(hdc, pPoints, iNumber);
Работа в режиме MM_TEXT
В режиме MM_TEXT заданы следующие величины начал координат и протяженностей:
Начало координат окна: (Window origin)
(0, 0)
Может быть изменено
Начало координат области вывода: (Viewport origin)
(0, 0)
Может быть изменено
Протяженность окна: (Window extent)
(1, 1)
Не может быть изменена
Протяженность области вывода: (Viewport extent)
(1, 1)
Не может быть изменена
Отношение протяженности области вывода к протяженности окна равно 1, таким образом, масштабирование между логическими и физическими координатами не производится. Формулы, приведенные выше, принимают вид:
xViewport = xWindow — xWinOrg + xViewOrg
yViewport = yWindow — yWinOrg + yViewOrg
Этот режим отображения называется "текстовым" не потому, что он наиболее удобен для вывода текста, а из-за направления осей координат.
Мы читаем текст слева направо и сверху вниз, и MM_TEXT аналогично задает направления увеличения координат:
Windows имеет функции SerViewportOrgEx и SetWindowOrgEx для изменения начала координат области вывода и окна. Эти функции обладают эффектом сдвига осей координат таким образом, что логическая точка (0, 0) не будет далее соответствовать левому верхнему углу рабочей области.
Чаще всего вы будете использовать SetViewportOrgEx или SetWindowOrgEx, но не обе функции одновременно.
Вот как работают эти функции. Если вы переносите начало координат области вывода в точку (xViewOrg,
yViewOrg), то логическая точка (0, 0) будет соответствовать физической точке с координатами (xViewOrg,
yViewOrg). Если вы переносите начало координат окна в точку (xWinOrg, yWinOrg), то логическая точка (xWinOrg,
yWinOrg) будет соответствовать физической точке с координатами (0, 0), т. е. левому верхнему углу рабочей области.
+X
+Y

104
Например, предположим, что рабочая область вашего окна имеет ширину cxClient и высоту cyClient пикселей.
Если вы хотите установить начало логической системы координат — точку (0, 0) — в центр рабочей зоны окна, вы можете это сделать так:
SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL);
Аргументы функции SetViewportOrgEx всегда задаются в координатах устройства.
Логическая точка (0, 0) будет теперь отображаться в точку с физическими координатами (cxClient/2, cyClient/2). Теперь вы используете рабочую область так, как будто бы она имела представленную ниже систему координат:
Значения логической координаты x могут изменяться в диапазоне от —cxClient/2 до
cxClient/2. Значения логической координаты y могут изменяться в диапазоне от
cyClient/2 до cyClient/2. Правый нижний угол рабочей области — точка с логическими координатами (cxClient/2, cyClient/2). Если вы хотите вывести текст, начиная от верхнего левого угла рабочей зоны, имеющего физические координаты (0, 0), вам необходимо задать отрицательные координаты:
TextOut(hdc, -cxClient / 2, -cyClient / 2, "Hello", 5);
Вы можете добиться того же результата, используя функцию SetWindowOrgEx вместо функции SetViewportOrgEx:
SetWindowOrgEx(hdc, -cxClient / 2, -cyClient / 2, NULL);
Аргументы функции SetWindowOrgEx всегда задаются в логических координатах. После этого вызова логическая точка (—cxClient/2, —cyClient/2) соответствует физической точке (0, 0) — левому верхнему углу рабочей области.
То, чего вы не должны делать (до тех пор, пока вы не будете знать, к чему это приведет) — это использовать обе функции совместно:
SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL);
SetWindowOrgEx(hdc, -cxClient / 2, -cyClient / 2, NULL);
Это означает, что логическая точка (—cxClient/2, —cyClient/2) соответствует физической точке (cxClient/2, cyClient/2), представляя вам такую систему координат:
Вы можете получить текущее положение начала координат области вывода и окна, используя функции:
GetViewportOrgEx(hdc, &pt);
GetWindowOrgEx(hdc, &pt); где pt — структура типа POINT (точка).
Функция GetViewportOrgEx возвращает значение в координатах устройства, а функция GetWindowOrgEx — в логических координатах.
Вы можете изменить начала координат области вывода и окна так, чтобы сдвинуть экранный вывод в рабочую зону вашего окна — например, в ответ на изменение пользователем состояния полосы прокрутки. Изменение начала координат области вывода или окна не приводит к немедленному сдвигу экранного вывода. Например, в программе
SYSMETS2 из главы 2 мы использовали значение iVscrollPos (текущее положение вертикальной полосы прокрутки) для вычисления соответствующей координаты y экранного вывода: case WM_PAINT :
BeginPaint(hwnd, &ps); for (i = 0; i < NUMLINES; i++)
{ y = cyChar *(1 — iVscrollPos + i);
[
вывод

текста
]
}
EndPaint(hwnd, &ps); return 0;
Мы можем добиться того же результата, используя функцию SetWindowOrgEx: case WM_PAINT :
BeginPaint(hwnd, &ps);
SetWindowOrgEx(ps.hdc, 0, cyChar * iVscrollPos); for (i = 0; i < NUMLINES; i++)
{
+X
+Y
— X
— Y
—X
—Y

105 y = cyChar *(1 + i);
[
вывод

текста
]
}
EndPaint(hwnd, &ps); return 0;
Теперь вычисление координаты y для функции TextOut не требует значения iVscrollPos. Это означает, что вы можете поместить функции вывода текста в подпрограмму, не передавая в нее значение iVscrollPos, так как мы настраиваем вывод текста путем изменения начала координат окна.
Если у вас есть опыт работы с прямоугольной (Декартовой) системой координат, то перенос логической точки (0,
0) в центр рабочей области, как мы сделали ранее, может показаться вам полезным. Тем не менее, тут есть небольшая проблема в режиме MM_TEXT: обычно в Декартовой системе координат значение координаты y увеличивается при перемещении вверх, а в режиме MM_TEXT — вниз. В этом смысле режим MM_TEXT несколько странноват, тогда как следующие пять режимов отображения делают это корректно.
Метрические режимы отображения
Windows включает пять режимов отображения для выражения логических координат в физических единицах измерения. Поскольку логические координаты по осям x и y преобразуются в одинаковые физические единицы измерения, эти режимы отображения помогают вам рисовать круглые окружности и квадратные квадраты.
Пять метрических режимов отображения (metric mapping modes) приведены ниже в порядке возрастания точности.
Для сравнения в двух правых столбцах приведены размеры логических единиц в дюймах и миллиметрах (мм).
Режим
отображения
Логическая
единица
Дюймы
Миллиметры
MM_LOENGLISH 0.01 дюйма 0.01 0.254
MM_LOMETRIC 0.1 миллиметра 0.00394 0.1
MM_HIENGLISH 0.001 дюйма 0.001 0.0254
MM_TWIPS
*
1/1440 дюйма 0.000694 0.0176
MM_HIMETRIC 0.01 миллиметра 0.000394 0.01
Для того, чтобы дать вам представление о том, как разрешение режима MM_TEXT соотносится с этими разрешениями, скажем, что на стандартном дисплее VGA, каждый пиксель которого имеет размер 0.325 мм в ширину и высоту, физические VGA — координаты грубее, чем логические координаты в любом из метрических режимов отображения.
На лазерном принтере с разрешением 300 точек/дюйм каждый пиксель имеет размер 0.0033 дюйма — это более высокое разрешение, чем в режимах MM_LOENGLISH и MM_LOMETRIC, но более низкое, чем в режимах
MM_HIENGLISH, MM_TWIPS и MM_HIMETRIC.
Начала координат и протяженности, заданные по умолчанию, приведены ниже:
Начало координат окна: (Window origin)
(0, 0)
Может быть изменено
Начало координат области вывода: (Viewport origin)
(0, 0)
Может быть изменено
Протяженность окна: (Window extent)
(?, ?)
Не может быть изменена
Протяженность области вывода: (Viewport extent)
(?, ?)
Не может быть изменена
Протяженности окна и области вывода зависят от режима отображения и коэффициента сжатия (aspect ratio) устройства (отношения высоты пикселя к его ширине). Как уже отмечалось ранее, протяженности сами по себе не имеют смысла. Имеет смысл только их отношение. Приведем формулы преобразования координат еще раз:
xViewport = (xWindow — xWinOrg)
×
(xViewExt/xWinExt) + xViewOrg
yViewport = (yWindow — yWinOrg)
×
(yViewExt/yWinExt) + yViewOrg,
В режиме MM_LOENGLISH, например, Windows вычисляет протяженности таким образом, чтобы соблюдались следующие соотношения:
xViewExt/xWinExt = число пикселей по горизонтали в 0.01 дюйма
-yViewExt/yWinExt = число пикселей по вертикали в 0.01 дюйма, взятое со знаком минус
Для многих дисплейных устройств (таких как VGA), коэффициент сжатия будет меньше 1. Поскольку Windows работает только с целыми числами, использование коэффициента сжатия более рационально, чем использование
*
Определенная выше единица измерения twip равна 1/20 точки (которая равна 1/72 дюйма) и точно равна 1/1440 дюйма.

106 абсолютных значений масштабных коэффициентов, для снижения погрешности при преобразовании логических и физических координат.
Обратите внимание на знак минус перед отношением протяженностей для вертикальной оси. Этот минус изменяет направление оси y.
Для пяти указанных режимов отображения, величина координаты y возрастает при движении вверх. Начала координат окна и области вывода по умолчанию равны (0,
0). Этот факт имеет интересное следствие. Когда вы впервые переключаетесь в один из этих пяти режимов отображения, система координат выглядит так:
Есть только один метод, позволяющий вам отобразить что-нибудь в рабочей области
— это использование отрицательных значений координаты y. Например, этот код:
SetMapMode(hdc, MM_LOENGLISH);
TextOut(hdc, 100, -100, "Hello", 5); выводит "Hello" с отступом в один дюйм слева и сверху рабочей области.
Чтобы избежать этого и работать в привычной системе координат, надо установить логическую точку (0, 0) в левый нижний угол рабочей зоны. Считая высоту рабочей зоны в пикселях равной cyClient, вы можете сделать это, вызвав функцию SetViewportOrgEx:
SetViewportOrgEx(hdc, 0, cyClient, NULL);
Теперь система координат выглядит так:
Аналогично, вы можете установить логическую точку (0, 0) в центр рабочей области:
SetViewportOrgEx(hdc, cxClient / 2, cyClient / 2, NULL);
Система координат будет выглядеть так:
Теперь мы имеем настоящую Декартову систему координат с одинаковыми логическими единицами измерения по осям x и y — дюймами, миллиметрами или единицами измерения twips.
Вы можете также использовать функцию SetWindowOrgEx для изменения логической точки (0, 0), но эта задача несколько сложнее, поскольку параметры функции должны задаваться в логических координатах. Вам следовало бы сначала преобразовать пару значений (cxClient, cyClient) в логические координаты, используя функцию DPtoLP. Считая, что переменная pt имеет тип структуры POINT, приведенный ниже код перемещает логическую точку (0,0) в центр рабочей области: pt.x = cxClient; pt.y = cyClient;
DPtoLP(hdc, &pt, 1);
SetWindowOrgEx(hdc, -pt.x / 2, -pt.y / 2, NULL);



Поделитесь с Вашими друзьями:
1   ...   7   8   9   10   11   12   13   14   ...   41


База данных защищена авторским правом ©nethash.ru 2019
обратиться к администрации

войти | регистрация
    Главная страница


загрузить материал