Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
gdi.doc
Скачиваний:
9
Добавлен:
15.09.2019
Размер:
306.18 Кб
Скачать

Лекция 5. Отображение информации с помощью модуля

GDI

1. Контекст устройства

В однозадачных ОС (MS-DOS), любая программа может рисовать непосредст-

венно на экране. В многозадачных ОС программы так действовать не должны, т.к.

при одновременной работе нескольких программ пользователь должен видеть на эк-

ране согласованную картину, сформированную в результате их совместной работы.

Экранная область, принадлежащая программе A, должна быть защищена от информа-

ции, выводимой программой B. Доступом к видеоадаптеру, как и к другим устройст-

вам, управляет ОС. Она позволяет программам выводить информацию только в пре-

делах их окон. В Windows графическое отображение выполняет модуль GDI.

Windows-приложение не может рисовать что-либо непосредственно на экране,

принтере или каком-нибудь другом устройстве вывода. Все операции рисования про-

изводятся на воображаемом "устройстве", представляемом с помощью контекста уст-

ройства. Контекст устройства – эта служебная внутренняя структура Windows, в

которой хранятся все характеристики устройства и его текущего состояния, необхо-

димые модулю GDI для рисования. До начала рисования приложение должно полу-

чить от модуля GDI дескриптор контекста устройства. Этот дескриптор надо переда-

вать в качестве первого параметра всем функциям рисования GDI. Без корректного

дескриптора контекста устройства, GDI не будет знать, на каком именно устройстве и

в какой его области рисовать пикселы. В контексте устройства хранятся параметры,

позволяющие GDI выполнять отсечение и рисовать графические примитивы только

внутри заданных областей. Одни и те же функции GDI могут рисовать примитивы на

различных устройствах, т.к. специфика устройства скрыта в контексте устройства.

MFC избавляет программиста от необходимости непосредственной работы с

дескрипторами контекстов устройств. Дескриптор контекста устройства и функции

рисования GDI инкапсулированы в класс "Контекст устройства" – CDC. От него унас-

ледованы классы для представления различных контекстов устройств (см. табл. 5.1).

Таблица 5.1. Классы различных контекстов устройств

Имя класса

CPaintDC

CClientDC

CWindowDC

С чем связан этот контекст устройства

Клиентская область окна (только в обработчиках OnPaint)

Клиентская область окна

Окно, включая неклиентскую область

CMetaFileDC Метафайл GDI (аналог макроса, в котором запоминаются вызовы функ-

ций GDI и потом их можно многократно воспроизводить)

Объекты этих классов можно создавать как автоматически, так и динамически.

В конструкторе и деструкторе каждого класса вызываются функции GDI для получе-

ния и освобождения дескрипторов контекста устройства. Например, создать контекст

устройства в обработчике OnPaint можно так:

CPaintDC dc(this);

// Вызовы каких-либо функций-членов для рисования примитивов

Конструктору CPaintDC передается указатель на окно, с которым будет связан

контекст устройства.

Класс CPaintDC предназначен для рисования в клиентской области окна при

обработке сообщений WM_PAINT. Но приложения Windows могут выполнять графиче-

56

ское отображение не только в OnPaint. Например, требуется рисовать в окне окруж-

ность при каждом щелчке мышью. Это можно делать в обработчике сообщения мы-

ши, не дожидаясь очередного сообщения WM_PAINT. Для подобных операций отобра-

жения предназначен класс CClientDC. Он создает контекст устройства, связанный с

клиентской областью окна, которым можно пользоваться за пределами OnPaint.

Ниже приведен пример рисования диагоналей в клиентской области окна с по-

мощью CClientDC и двух функций-членов, унаследованных от CDC.

void CMainWindow::OnLButtonDown( UINT nFlags, CPoint point )

{

CRect rect;

GetClientRect(&rect);

CClientDC dc(this);

dc.MoveTo( rect.left, rect.top );

dc.LineTo( rect.right, rect.bottom );

dc.MoveTo( rect.right, rect.top );

dc.LineTo( rect.left, rect.bottom );

}

В редких случаях программе требуется получить доступ ко всему экрану (на-

пример, в программе захвата экрана). Тогда можно создать контекст устройства как

объект класса CClientDC или CWindowDC, но в конструктор передать нулевой указа-

тель. Например, нарисовать окружность в левой верхней части экрана можно так:

CClientDC dc( NULL );

dc.Ellipse( 0, 0, 100, 100 );

1.1 Атрибуты контекста устройства

В контексте устройства хранится ряд атрибутов, влияющих на работу функций

рисования. В классе CDC есть функции-члены для чтения текущих значений и для из-

менения этих атрибутов (табл. 5.2).

Таблица 5.2. Основные атрибуты контекста устройства

Атрибут

Цвет текста

Цвет фона

Режим фона

Режим преобразова-

ния координат

Режим рисования

Текущая позиция

Текущее перо

Текущая кисть

Текущий шрифт

Значение по

умолчанию

Черный

Белый

OPAQUE

MM_TEXT

R2_COPYPEN

(0,0)

BLACK_PEN

WHITE_BRUSH

SYSTEM_FONT

Функция-член CDC для

задания значения

SetTextColor

SetBkColor

SetBkMode

SetMapMode

SetROP2

MoveTo

SelectObject

SelectObject

SelectObject

Функция-член СDC для

получения значения

GetTextColor

GetBkColor

GetBkMode

GetMapMode

GetROP2

GetCurrentPosition

SelectObject

SelectObject

SelectObject

Различные функции рисования CDC пользуются атрибутами по-разному. На-

пример, цвет, ширина и стиль (сплошная, штриховая и т.п.) линии для рисования от-

резка функцией LineTo определяются текущим пером. При рисовании прямоуголь-

ника функцией Rectangle модуль GDI рисует контур текущим пером, а внутреннюю

область заполняет текущей кистью. Цвет текста, фона и шрифт используются всеми

функциями отображения текста. Фоновый цвет применяется также при заполнении

57

промежутков в несплошных линиях. Если фоновый цвет не нужен, его можно отклю-

чить (сделать "прозрачным"):

dc.SetBkMode( TRANSPARENT );

Атрибуты CDC чаще всего изменяются с помощью функции SelectObject.

Она предназначена для "выбора" в контексте устройства объектов GDI 6-ти типов:

• перья (pens)

• кисти (brushes)

• шрифты (fonts)

• битовые карты (bitmaps)

• палитры (palettes)

• области (regions).

В MFC перья, кисти и шрифты представлены классами CPen, CBrush и CFont.

Свойства пера "по умолчанию": сплошная черная линия толщиной 1 пиксел; кисть

"по умолчанию": сплошная белая; шрифт "по умолчанию": пропорциональный

высотой примерно 12 пт. Вы можете создавать объекты-перья, кисти и шрифты с

нужными вам свойствами и выбирать их в любом контексте устройства.

Допустим, динамически были созданы объекты pPen и pBrush – черное перо

толщиной 10 пикселов и сплошная красная кисть. Для рисования эллипса с черным

контуром и красным заполнением можно вызвать следующие функции-члены:

dc.SelectObject( pPen );

dc.SelectObject( pBrush );

dc.Ellipse( 0, 0, 100, 100 );

Функция-член SelectObject перегружена для работы с указателями на раз-

личные объекты GDI. Она возвращает указатель на предыдущий выбранный в кон-

тексте устройства объект того же типа, что и объект, переданный функции в качестве

параметра.

1.2 Режимы преобразования координат

Один из самых сложных для освоения аспектов GDI – применение режимов

преобразования координат. Режим преобразования координат – это атрибут контек-

ста устройства, задающий способ пересчета логических координат в физические ко-

ординаты устройства. Логические координаты передаются функциям рисования CDC.

Физические координаты – это координаты пикселов в экранном окне или на листе

принтера (т.е. на поверхности изображения).

Допустим, вызывается функция Rectangle:

dc.Rectangle( 0, 0, 200, 100 );

Нельзя сказать, что эта функция нарисует прямоугольник шириной 200 пиксе-

лов и высотой 100 пикселов. Она нарисует прямоугольник шириной 200 логических

единиц и высотой 100 единиц. В режиме преобразования координат по умолчанию,

MM_TEXT, 1 логическая единица равна 1-му пикселу. В других режимах масштаб мо-

жет быть иным (см. табл. 5.3). Например, в режиме MM_LOMETRIC 1 логическая еди-

ница равна 1/10 мм. Следовательно, в показанном вызове Rectangle будет нарисован

прямоугольника шириной 20 мм и высотой 10 мм. Режимы, отличные от MM_TEXT,

удобно применять для рисования в одинаковом масштабе на различных устройствах

вывода.

58

Таблица 5.3. Режимы преобразования координат, поддерживаемые модулем GDI

Константа для обозначе-

ния режима

MM_TEXT

MM_LOMETRIC

MM_HIMETRIC

MM_LOENGLISH

MM_HIENGLISH

Расстояние, соответствующее

логической единице

1 пиксел

0.1 мм

0.01 мм

0.01 дюйма

0.001 дюйма

Ориентация координат-

ных осей

x вправо, у вниз

x вправо, у вверх

x вправо, у вверх

x вправо, у вверх

x вправо, у вверх

MM_TWIPS

1/1440 дюйма (0.0007 дюйма) x вправо, у вверх

MM_ISOTROPIC

MM_ANISOTROPIC

Определяется пользователем

(масштаб по осям x и y одина-

ков)

Определяется пользователем

(масштаб по осям x и y задается

независимо)

Определяется пользовате-

лем

Определяется пользовате-

лем

Система координат в режиме MM_TEXT показана на рис. 5.1. Начало координат

располагается в левом верхнем углу поверхности изображения (в зависимости от кон-

текста устройства, это может быть левый верхний угол экрана, окна, клиентской об-

ласти окна). Ось х направлена вправо, ось y вниз, 1 логическая единица равна 1-му

пикселу. В остальных, "метрических", системах ось y направлена вверх, так что сис-

тема координат оказывается правой, но начало координат по умолчанию всегда по-

мещается в левый верхний угол поверхности изображения.

(0, 0)

x

Поверхность изображения

1 единица = 1 пиксел

y

Рис. 5.1. Система координат в режиме MM_TEXT.

1.3 Функции преобразования координат

Для преобразования логических координат в координаты устройства (физиче-

ские координаты) предназначена функция CDC::LPtoDP. Для обратного преобразо-

вания есть функция CDC::DPtoLP.

Допустим, надо вычислить координаты центра клиентской области окна в фи-

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

клиентской области в пикселах возвращает функция CWnd::GetClientRect:

CRect rect;

GetClientRect( &rect );

CPoint point( rect.Width()/2, rect.Height()/2 );

Для вычисления координат этой точки в режиме MM_LOMETRIC потребуется

функция DPtoLP:

CRect rect;

GetClientRect( &rect );

CPoint point( rect.Width()/2, rect.Height()/2 );

CClientDC dc( this );

dc.SetMapMode( MM_LOMETRIC );

59

dc.DPtoLP( &point );

Функции LPtoDP и DPtoLP часто применяются при обработке сообщений мы-

ши. Windows помещает в структуру сообщения координаты указателя в физической

системе координат. Поэтому, если вы ходите "нарисовать мышью" прямоугольник в

режиме MM_LOMETRIC, то перед рисованием необходимо преобразовать координаты

указателя из физических координат устройства в логические координаты контекста.

Иногда Windows-программисты употребляют термины "клиентские координа-

ты" и "экранные координаты". Клиентские координаты – это физические координаты,

заданные относительно левого верхнего угла клиентской области окна. Экранные ко-

ординаты – это физические координаты, заданные относительно левого верхнего угла

экрана. Преобразование между двумя этими системами выполняется с помощью

функций CWnd::ClientToScreen и CWnd::ScreenToClient.

1.4 Изменение положения начала координат

По умолчанию во всех режимах преобразования координат начало логической

системы координат располагается в левом верхнем углу поверхности изображения.

При работе с правыми системами координат м.б. удобнее поместить начало системы

в другую точку, например, в центр или левый нижний угол окна. Для этого можно

использовать одну из двух функций: CDC::SetWindowOrg (смещение левого верхне-

го угла поверхности изображения) или CDC::SetViewportOrg (смещение начала ло-

гической системы координат).

Предположим, требуется поместить начало логической системы координат в

центр окна. Это можно сделать так (считая, что dc – объект подкласса CDC):

CRect rect;

GetClientRect( &rect );

dc.SetViewportOrg( rect.Width()/2, rect.Height()/2 );

1.5 Получение характеристик устройства

Иногда бывает полезно узнать характеристики устройства, с которым связан

контекст. Для этого предназначена функция CDC::GetDeviceCaps. Например, полу-

чить ширину и высоту экрана (например, 1024х768) можно так:

CClientDC dc( this );

int cx = dc.GetDeviceCaps( HORZRES );

int cy = dc.GetDeviceCaps( VERTRES );

Некоторые возможные параметры функции GetDeviceCaps приведены в табл. 5.4.

Таблица 5.4. Часто используемые параметры функции GetDeviceCaps

Параметр

Значение, возвращаемое функцией GetDeviceCaps

HORZRES Ширина поверхности изображения, в пикселах

VERTRES

HORZSIZE

VERTSIZE

Высота поверхности изображения, в пикселах

Ширина поверхности изображения, в миллиметрах

Высота поверхности изображения, в миллиметрах

LOGPIXELSX Количество пикселов на логический дюйм по горизонтали

LOGPIXELSY Количество пикселов на логический дюйм по вертикали

NUMCOLORS Для дисплея – количество статических цветов, для принтера или плоттера –

количество поддерживаемых цветов

TECHNOLOGY Получение битовых флагов, идентифицирующих тип устройства – дисплей,

принтер, плоттер и др.

60

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]