Текущий режим отображения (mappind mode)




Макрос Режим отображения
  MM_ANISOTROPIC Режим логических единиц, определенных программистом, с различным масштабированием по осям координат
  MM_HIENGLISH Одна логическая единица равна 0,001 дюйма
  MM_HIMETRIC Одна логическая единица равна 0,01 миллиметра
  MM_ISOTROPIC Режим логических единиц, определенных программистом, с эквивалентным масштабированием по осям координат (соотношение координат по различным осям устанавли­вается один к одному)
  MM_LOMETRIC Одна логическая единица равна 0,1 миллиметра
  MM_LOENGLISH Одна логическая единица равна 0,01 дюйма
  ММ_ТЕХТ Одна логическая единица равна 1 пикселю
  MM_TWIPS Одна логическая единица равна 1/12 точки принтера, т.е. примерно 1/1440 дюйма

 

Функция SetMapMode() возвращает значение, соответствующее прежнему режи­му отображения, или нуль в случае возникновения ошибки. По умолчанию устанав­ливается режим ММ_ТЕХТ.

Существует несколько причин для изменения режима отображения в программе. Во-первых, Вам может понадобиться, чтобы размеры объектов, отображаемых про­граммой, соответствовали размерам реальных физических объектов, – в этом случае нужно установить один из режимов, соответствующих реальным метрическим еди­ницам, например MM_LOMETRIC. Во-вторых, Вы можете пожелать задействовать в своей программе те единицы измерения, которые используются для объектов реального мира. В-третьих, может возникнуть необходимость изменить масштаб изображения (увеличить или уменьшить его, сохраняя или изменяя при этом пропор­ции объектов). И, наконец, может потребоваться установить соотношение размеров по осям X и Y один к одному; в последнем случае каждая логическая единица по оси X будет иметь тот же физический размер, что и логическая единица по оси Y.

Замечание: Изменение режима отображения изменяет способ преобразования логических единиц координат в физические (пиксели).

 


Определение логических размеров окна. Режимы отображения MM_ISOTROPIC и MM_ANISOTROPIC позволяют задать размеры окна в логических единицах. Задав один из этих режимов, необходимо также определить размеры окна (поскольку режимы MM_ISOTROPIC и MM_ANISOTROPIC используются только для программно определенных логических единиц, физические размеры Окна остаются неопределенными до тех пор, пока Вы не зададите их явно). Для задания размеров окна (extents) используется функция API SetWindowExtEx(), имеющая следующий прототип:

 

BOOL SetWindowExtEx(HDC hdc, int Xextent, int Yextent, LPSIZE size);

 

Параметр hdc содержит дескриптор контекста устройства. Параметры Xextent и Yextent задают размеры (extents) окна по горизонтали и вертикали в логических единицах. Предыдущие размеры окна копируются в структуру типа SIZE, указатель на которую задается параметром size. Если этот параметр равен NULL, предыдущие размеры окна не возвращаются. Функция возвращает ненулевое значение в случае успешного завершения либо нуль при возникновении ошибки. Вызов функции SetWindowExtEx() имеет смысл только в том случае, если установлены режимы отображения MM_ISOTROPIC и MM_ANISOTROPIC.

Структура SIZE определяется следующим образом:

 

typedef struct tagSIZE

{

LONG ex; // Ширина

LONG су; // Высота

} SIZE;

 

Заметьте, что, изменяя логические размеры окна, Вы не изменяете его физические размеры на экране: Вы просто определяете размеры окна в установленных Вами логических единицах (или, точнее, определяете соотношение логических единиц, используемых окном, и физических единиц – пикселей, используемых устройством отображения). Так, одно и то же реальное окно может иметь логические размеры 100 на 100 или 50 на 75. Разница будет только в соотношении логических единиц и пикселей при выводе графических объектов.

 

Определение области вывода. Как уже упоминалось, область вывода (viewport) – это область, в которую физически выводится информация. Размеры области вывода можно определить при помощи функции SetViewportExtEx():

 

BOOL SetViewportExtEx(HOC hdc, int Xextent, int Yextent, LPSIZE size};

 


Здесь параметр hdc задает дескриптор контекста устройства, а параметры Xextent и Yextent – размеры области вывода по горизонтали и вертикали в пикселях. Функция возвращает ненулевое значение при нормальном завершении и нуль при возникно­вении ошибки. Прежние размеры области вывода возвращаются в структуре SIZE, указатель на которую задается параметром size. Если этот указатель равен NULL, прежние размеры области вывода игнорируются. Вызов функции SetViewportExtEx() имеет смысл только после установки режима отображения MM_ISOTROPIC или MM_ANISOTROPIC.

Можно установить любые размеры для области вывода, поэтому она может быть и больше, и меньше окна. Для режима отображения MM_TEXT, устанавливаемого по умолчанию, размер области вывода всегда равен размеру окна.

Вывод программы автоматически отображается из контекста устройства окна (в логических единицах) в область вывода (в пикселях) и соответственно масштабирует­ся. Поэтому, изменяя размеры области вывода, Вы изменяете видимые размеры отображаемых в ней объектов. Таким образом, при увеличении размеров области вывода содержимое ее тоже увеличится и, наоборот, – при уменьшении размеров области вывода ее содержимое уменьшится. Это будет показано в следующем примере.

 

Задание начала области вывода. По умолчанию область вывода начинается в точке 0,0 в рабочей области окна. Однако начальной можно сделать другую точку при помощи функции SetViewportOrgEx(), имеющей следующий прототип:

 

BOOL SetViewportOrgEx(HDC hdc, int X, int Y, LPPOINT OldOrg);

 

Параметр hdc должен задавать дескриптор контекста устройства. Новая точка начала области вывода задается параметрами X и Y. Координаты прежнего начала области вывода записываются в структуру POINT, указатель на которую задается параметром OldOrg. Этот параметр может быть равен NULL, и тогда координаты предыдущей области вывода будут игнорироваться.

Изменение начала области вывода приводит к тому, что выводимая в окно информация будет отображаться в другом месте. В приведенном ниже примере будет показано, как это можно осуществить.

 

Пример 9-2. Приведенная ниже программа представляет собой расширенную версию про­граммы предыдущего примера. В нее добавлены операции установки режима отоб­ражения, логических размеров окна и размеров области вывода. Программа устанавливает режим отображе­ния MM_ANISOTROPIC, логические размеры окна 200´200 и размеры области вывода 10´10. При каждом выборе команды меню Размер размеры области вывода увеличиваются на 10, что влечет за собой увеличение изображения на экране. По команде Начало вывода координаты начала области вывода увеличиваются на 50 пикселей.

 

// Установка режимов вывода, размеров окна и области

// вывода

#include <Windows.h>

#include <String.h>

#include <Stdio.h>

#include "Graph.h"

 

LRESULT CALLBACK WindowFunc(HWND,UINT,WPARAM,LPARAM);

char szWinName[] = "МоеОкно"; // Имя класса окна

char str[255]; // Буфер строки вывода

int maxX, maxY; // Размеры экрана

int X=10, Y=10; // Размеры области вывода

int orgX=0, orgY=0; // Координаты области вывода

HDC memdc; // DC виртуального окна

HBITMAP hbit; // Растр - это виртуальное окно

HBRUSH hbrush, hOldbrush; // Дескрипторы кистей

HPEN hOldpen; // Дескриптор прежнего пера

HPEN hRedpen,hGreenpen,hBluepen,hYellowpen; // Перья

 

int WINAPI WinMain (HINSTANCE hThisInst,

HINSTANCE hPrevInst,

LPSTR lpszArgs,

int nWinMode)

{

HWND hwnd;

MSG msg;

WNDCLASS wcl;

HACCEL hAccel;

// Определить класс окна

wcl.hInstance=hThisInst; // Дескриптор приложения

wcl.lpszClassName=szWinName; // Имя класса окна

wcl.lpfnWndProc=WindowFunc; // Функция окна

wcl.style=0; // Стиль по умолчанию

wcl.hIcon=LoadIcon(NULL,IDI_APPLICATION); // Иконка

wcl.hCursor=LoadCursor(NULL,IDC_ARROW); // Курсор

wcl.lpszMenuName="MYMENU"; // Меню

wcl.cbClsExtra=0; // Без дополнительной

wcl.cbWndExtra=0; // информации

// Определить заполнение окна белым цветом

wcl.hbrBackground=

(HBRUSH)GetStockObject(WHITE_BRUSH);

if(!RegisterClass(&wcl)) // Зарегистр. класс окна

return 0;

// Создать окно

hwnd=CreateWindow(szWinName, // Имя класса

"Работа с графикой: режимы вывода",

WS_OVERLAPPEDWINDOW,// Стиль окна

CW_USEDEFAULT, // Х-координата

CW_USEDEFAULT, // Y-координата

CW_USEDEFAULT, // Ширина окна

CW_USEDEFAULT, // Высота окна

HWND_DESKTOP, // Нет родит. окна

NULL, // Нет меню

hThisInst, // Дескрип. приложения

NULL); // Без дополит. аргументов

// Загрузить акселераторы

hAccel=LoadAccelerators(hThisInst,"MYMENU");

ShowWindow(hwnd,nWinMode); // Показать окно и

UpdateWindow(hwnd); // перерисовать содержимое

// Запустить цикл обработки сообщений

while(GetMessage (&msg,NULL,0,0))

if(!TranslateAccelerator(hwnd,hAccel,&msg))

{

TranslateMessage(&msg); // Использ.Клавиатуры

DispatchMessage (&msg); // Возврат к Windows

}

return msg.wParam;

}

 

// Следующая функция вызывается операционной системой

// Windows и получает в качестве параметров сообщения

// из очереди сообщений данного приложения

 

LRESULT CALLBACK WindowFunc(HWND hwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

HDC hdc;

PAINTSTRUCT paintstruct;

switch(message)

{

case WM_CREATE: // Получаем размеры экрана

maxX=GetSystemMetrics(SM_CXSCREEN);

maxY=GetSystemMetrics(SM_CYSCREEN);

hdc=GetDC(hwnd); // Совмест. с окном растр

memdc=CreateCompatibleDC(hdc);

hbit=CreateCompatibleBitmap(hdc,maxX,maxY);

SelectObject(memdc,hbit);

hbrush=(HBRUSH)GetStockObject(WHITE_BRUSH);

SelectObject(memdc,hbrush);

PatBlt(memdc,0,0,maxX,maxY,PATCOPY);

// Создать новые перья

hRedpen =CreatePen(PS_SOLID,1,RGB(255,0,0));

hGreenpen=CreatePen(PS_SOLID,1,RGB(0,255,0));

hBluepen =CreatePen(PS_SOLID,1,RGB(0,0,255));

hYellowpen=

CreatePen(PS_SOLID,1,RGB(255,255,0));

hOldpen=(HPEN)SelectObject(memdc,hRedpen);

SelectObject(memdc,hOldpen); // Старое перо

ReleaseDC(hwnd,hdc);

break;

case WM_COMMAND:

switch(LOWORD(wParam))

{

case ID_LINES:

// Вывести 2 черных пикселя

SetPixel(memdc,40,14,RGB(0,0,0));

SetPixel(memdc,40,15,RGB(0,0,0));

// Вывести прямую линию

LineTo(memdc,100,50);

MoveToEx(memdc,100,50,NULL);

// Установить зеленое перо

hOldpen=

(HPEN)SelectObject(memdc,hGreenpen);

LineTo(memdc,200,100);

// Установить желтое перо

SelectObject(memdc,hYellowpen);

LineTo(memdc,0,200);

// Установить синее перо

SelectObject(memdc,hBluepen);

LineTo(memdc,200,200);

// Установить красное перо

SelectObject(memdc,hRedpen);

LineTo(memdc,0,0);

// Вернуться к прежнему перу

SelectObject (memdc, hOldpen);

// Провести дугу

Arc(memdc,0,0,300,300,0,50,200,50);

// Показать линии, отрезающие дугу

MoveToEx(memdc,150,150,NULL);

LineTo(memdc,0,50);

MoveToEx(memdc,150,150,NULL);

LineTo(memdc,200,50);

InvalidateRect(hwnd,NULL,1);

break;

case ID_RECTANGLES:

// Прямоугольники не заполняются

hOldbrush=(HBRUSH)SelectObject(memdc,

GetStockObject(HOLLOW_BRUSH));

// Рисуем прямоугольники

Rectangle(memdc,50,50,300,300);

RoundRect(memdc,125,125,220,240,15,13);

// Выбираем красное перо

SelectObject(memdc,hRedpen);

Rectangle(memdc,100,100,200,200);

SelectObject(memdc,hOldpen);

// Вернуться к прежнему перу

// Восстановить прежнюю кисть

SelectObject(memdc,hOldbrush);

InvalidateRect(hwnd,NULL,1);

break;

case ID_ELLIPSES:

// Создаем синюю кисть

hbrush=CreateSolidBrush(RGB(0,0,255));

hOldbrush=

(HBRUSH)SelectObject(memdc,hbrush);

// Рисуем эллипсы с синим заполнением

Ellipse(memdc,50,200,100,280);

Ellipse(memdc,75,25,280,100);

// Рисуем красным пером, зеленой кистью

SelectObject(memdc,hRedpen);

DeleteObject(hbrush); // Удалить кисть

// Создать зеленую кисть

hbrush=CreateSolidBrush(RGB(0,255,0));

SelectObject(memdc,hbrush);

Ellipse(memdc,100,100,200,200);

// Рисуем сектор

Pie(memdc,200,200,340,340,225,200,

200,250);

SelectObject(memdc,hOldpen);

// Вернуться к прежнему перу

SelectObject(memdc,hOldbrush);

// Восстановить прежнюю кисть и удалить

DeleteObject(hbrush); // зеленую кисть

InvalidateRect(hwnd,NULL,1);

break;

case ID_SIZE:

X += 10;

Y += 10;

InvalidateRect(hwnd,NULL,1);

break;

case ID_ORG:

orgX += 10;

orgY += 10;

InvalidateRect(hwnd,NULL,1);

break;

case ID_RESET:

// Восстановить текущую позицию в 0,0

MoveToEx(memdc,0,0,NULL);

// Стереть изображение при помощи

// перерисовки фона

PatBlt(memdc,0,0,maxX,maxY,PATCOPY);

InvalidateRect(hwnd,NULL,1);

break;

case ID_HELP:

MessageBox(hwnd,

"F2: линии\n"

"FЗ: прямоугольники\n"

"F4: эллипсы\n"

"F5: увеличить область\n"

"F6: изменить координаты\n"

"F7: сброс",

"Работа с графикой",MB_OK);

break;

}

break;

case WM_PAINT: // Перерисовка окна

// Получить DC */

hdc=BeginPaint(hwnd,&paintstruct);

// Установить режим вывода, границы окна и

// области вывода

SetMapMode(hdc,MM_ANISOTROPIC);

SetWindowExtEx(hdc,200,200,NULL);

SetViewportExtEx(hdc,X,Y,NULL);

SetViewportOrgEx(hdc,orgX,orgY,NULL);

// Теперь копируем растр из памяти на экран

BitBlt(hdc,0,0,maxX,maxY,memdc,0,0,SRCCOPY);

// Освободить DC

EndPaint(hwnd,&paintstruct);

break;

case WM_DESTROY: // Завершение программы

// Удалить созданные перья

DeleteObject(hRedpen);

DeleteObject(hGreenpen);

DeleteObject(hBluepen);

DeleteObject(hYellowpen);

DeleteDC(memdc); // Удалить виртуальное окно

PostQuitMessage(0);

break;

default:

// Все сообщения, не обрабатываемые в данной

// функции, направляются на обработку по

// умолчанию

return DefWindowProc(hwnd,message,

wParam,lParam);

}

return 0;

}

 

Эта программа требует следующий файл ресурсов:

 

#include <Windows.h>

#include "Graph.h"

MYMENU MENU

{

MENUITEM "&Линии", ID_LINES

MENUITEM "&Прямоугольники", ID_RECTANGLES

MENUITEM "&Эллипсы", ID_ELLIPSES

MENUITEM "&Размер", ID_SIZE

MENUITEM "&Начало вывода", ID_ORG

MENUITEM "&Cбpоc", ID_RESET

MENUITEM "Помощь", ID_HELP

}

MYMENU ACCELERATORS

{

VK_F2, ID_LINES, VIRTKEY

VK_F3, ID_RECTANGLES, VIRTKEY

VK_F4, ID_ELLIPSES, VIRTKEY

VK_F5, ID_SIZE, VIRTKEY

VK_F6, ID_ORG, VIRTKEY

VK_F7, ID_RESET, VIRTKEY

VK_F1, ID_HELP, VIRTKEY

}

 

Результат работы этой программы представлен на рис. 9.3.


Рис. 9.3. Режимы вывод графических объектов: а – с уменьшением,

б – с увеличением, в – с изменением начала области вывода

 

Следует учесть, что файл определений Graph.h должен быть дополнен двумя константами, и иметь следующий вид:

 

#define ID_LINES 100

#define ID_RECTANGLES 101

#define ID_ELLIPSES 102

#define ID_SIZE 103

#define ID_ORG 104

#define ID_RESET 105

#define ID_HELP 106

 

В следующей главе мы вернемся к разговору об элементах управления, приступив к рассмотрению общих элементов управления в Windows.

 




Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-03-31 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: