Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь FAQ Написать работу КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Изменение положения начала координатСодержание книги
Поиск на нашем сайте
По умолчанию во всех режимах преобразования координат начало логической системы координат располагается в левом верхнем углу поверхности изображения. При работе с правыми системами координат м.б. удобнее поместить начало системы в другую точку, например, в центр или левый нижний угол окна. Для этого можно использовать одну из двух функций: CDC::SetWindowOrg (смещение левого верхнего угла поверхности изображения) или CDC::SetViewportOrg (смещение начала логической системы координат). Предположим, требуется поместить начало логической системы координат в центр окна. Это можно сделать так (считая, что dc – объект подкласса CDC):
Получение характеристик устройства Иногда бывает полезно узнать характеристики устройства, с которым связан контекст. Для этого предназначена функция CDC::GetDeviceCaps. Например, получить ширину и высоту экрана (например, 1024х768) можно так:
Некоторые возможные параметры функции GetDeviceCaps приведены в табл. 5.4. Таблица 5.4. Часто используемые параметры функции GetDeviceCaps
Рисование графических примитивов с помощью функций GDI Рисование отрезков и кривых Основные (хотя и не все) функции-члены CDC, предназначенные для рисования отрезков и кривых, приведены в таблице 5.5. Таблица 5.5. Функции-члены CDC для рисования отрезков и кривых
Для рисования отрезка надо поместить текущую позицию в один из концов отрезка и вызвать LineTo с координатами второго конца:
При выводе нескольких соединяющихся отрезков MoveTo достаточно вызвать только для одного из концов первого отрезка, например:
Несколько отрезков можно построить одним вызовом Polyline или PolylineTo (отличие между ними в том, что PolylineTo пользуется текущей позицией, а Polyline – нет). Например, квадрат можно нарисовать так:
или с помощью PolylineTo:
Для рисования дуг окружностей и эллипсов предназначена функция CDC::Arc. В качестве параметров ей передаются координаты описывающего эллипс прямоугольника и координаты начальной и конечной точек дуги (эти точки задают углы для вырезания дуги из эллипса, поэтому могут точно на него не попадать). Ниже приведен пример для рисования левой верхней четверти эллипса шириной 200 единиц и высотой 100 единиц:
Важная особенность всех функций GDI для рисования отрезков и кривых в том, что последняя точка не рисуется. Т.е. при рисовании отрезка из точки (0, 0) в точку (100, 100):
пиксел (100, 100) принадлежать отрезку не будет. Если необходимо, чтобы последний пиксел тоже был закрашен цветом отрезка, это можно сделать с помощью функции CDC::SetPixel, предназначенной для закраски отдельных пикселов.
Рисование эллипсов, многоугольников и других фигур В GDI есть функции для рисования более сложных примитивов, чем отрезки и кривые. Некоторые из них перечислены в табл. 5.6. Таблица 5.6. Функции-члены CDC для рисования замкнутых фигур
Функциям GDI, рисующим замкнутые фигуры, передаются координаты описывающего прямоугольника. Например, чтобы функцией Ellipse нарисовать окружность, надо указать не центр и радиус, а описывающий квадрат, например:
Координаты описывающего прямоугольника можно передавать в виде структуры RECT или как объект CRect:
Как и последняя точка отрезка, нижняя строка и правый столбец описывающего прямоугольника не заполняются. Т.е. при вызове CDC::Rectangle:
результат будет такой, как на рис. 5.2.
Рис. 5.2. Прямоугольник, нарисованный вызовом dc.Rectangle(0,0,8,4)
Перья GDI и класс CPen Для рисования отрезков, кривых и контуров фигур GDI использует объект-перо, выбранное в контексте устройства. По умолчанию перо рисует сплошную черную линию толщиной 1 пиксел. Изменить вид линий можно, если создать соответствующий объект-перо и выбрать его в контексте устройства функцией CDC::SelectObject. В MFC перья GDI представляются в виде объектов класса CPen. Проще всего указать характеристика пера в конструкторе CPen, например:
Второй способ: создать неинициализированный объект CPen, а затем создать перо GDI вызовом CPen::CreatePen:
Третий способ: создать неинициализированный объект CPen, заполнить структуру LOGPEN характеристиками пера, а затем вызвать CPen::CreatePenIndirect для создания пера GDI:
В структуре LOGPEN поле lopnWidth имеет тип POINT, но координата y не используется, а x задает толщину пера. Функции CreatePen и CreatePenIndirect возвращают TRUE, если перо было успешно создано (FALSE – если перо создать не удалось). У пера есть три параметра: стиль, толщина и цвет. Возможные стили показаны на рис. 5.3.
Рис. 5.3. Стили пера.
Стиль PS_INSIDEFRAME предназначен для рисования линий, которые всегда располагаются внутри описывающего прямоугольника фигуры. Допустим, вы рисуете окружность диаметром 100 единиц пером PS_SOLID толщиной 20 единиц. Тогда реальный диаметр окружности по внешней границе будет 120 единиц (см. рис.5.4). Если ту же окружность нарисовать пером стиля PS_INSIDEFRAME, то диаметр окружности будет действительно 100 единиц. На рисование отрезков и других примитивов, не имеющих описывающего прямоугольника, стиль PS_INSIDEFRAME не влияет.
Рис. 5.4. Стиль пера PS_INSIDEFRAME.
Стиль PS_NULL бывает нужен для рисования фигур без контура (например, эллипсов), только с заполнением внутренней области. Толщина пера задается в логических единицах. Перья стилей PS_DASH, PS_DOT, PS_DASHDOT и PS_DASHDOTDOT должны быть обязательно толщиной 1 единица. Если задать толщину 0 единиц, то будет создано перо шириной 1 пиксел независимо от режима преобразования координат. Чтобы использовать новое перо, его надо выбрать в контексте устройства. Например, чтобы нарисовать эллипс красным пером толщиной 10 единиц, можно выполнить следующие действия:
Кисти GDI и класс CBrush По умолчанию внутренняя область замкнутых фигур (Rectangle, Ellipse и т.п.) заполняется белыми пикселами. Цвет и стиль заливки определяется параметрами кисти, выбранной в контексте устройства. В MFC кисть представляется классом CBrush. Бывают три типа кистей: сплошные, штриховые и шаблонные. Сплошные кисти рисуют одним цветом. Для штриховых кистей есть 6 предопределенных стилей, они чаще всего используются в инженерных и архитектурных чертежах (рис. 5.5). Шаблонные кисти рисуют путем повторения небольшой битовой карты. У класса CBrush есть конструкторы для создания кистей каждого типа.
Рис. 5.5. Стили штриховых кистей.
Для создания сплошной кисти в конструкторе CBrush достаточно указать значение цвета:
или создать кисть в два этапа (сначала объект MFC, затем объект GDI):
При создании штриховых кистей в конструкторе CBrush указываются стиль и цвет кисти, например:
или:
При рисовании штриховой кистью GDI заполняет "пустые" места цветом фона (по умолчанию белый, его можно изменить функцией CDC::SetBkColor или включить/выключить заполнение фона режимом OPAQUE или TRANSPARENT с помощью CDC::SetBkMode). Например, заштрихованный квадрат со стороной 100 единиц можно нарисовать так:
Отображение текста В предыдущей лекции уже упоминался один из способов вывода текста в окно с помощью функции CDC::DrawText. Ей можно указать прямоугольник, внутри которого выводить текст, и флаги, указывающие, как именно располагать текст внутри прямоугольника. Например, для вывода текста в виде одной строки по центру прямоугольника rect использовался вызов:
Кроме DrawText, в классе CDC есть еще несколько функций для работы с текстом. Некоторые из них приведены в табл. 5.7. Одна из самых часто используемых – функция TextOut, которая выводит текст подобно DrawText, но принимает в качестве параметров координаты точки начала вывода текста или использует для этого текущую позицию. Оператор:
выведет строку "Hello, MFC", начиная с левого верхнего угла окна, связанного с контекстом dc. Функция TabbedTextOut при выводе строки заменяет символы табуляции на пробелы (массив позиций табуляции передается в качестве параметра). По умолчанию, координаты, переданные в TextOut, TabbedTextOut и ExtTextOut, считаются левым верхнем углом описывающего прямоугольника для первого символа строки. Однако интерпретацию координат можно изменить, задав в контексте устройства свойство выравнивания текста. Для этого используется функция CDC::SetTextAlign, например, для выравнивания текста по правой границе:
Чтобы функция TextOut вместо явно указанных координат пользовалась текущей позицией, надо вызвать SetTextAlign с указанием стиля и установленным флагом TA_UPDATECP. Тогда TextOut после вывода каждой строки будет изменять текущую позицию. Так можно вывести несколько строк подряд с сохранением корректного расстояния между ними. Таблица 5.7. Функции-члены CDC для вывода текста
Функции GetTextMetrics и GetTextExtentпредназначены для получения свойств текущего шрифта, выбранного в контексте устройства. GetTextMetrics возвращает эти свойства в виде структуры TEXTMETRIC. GetTextExtent (или GetTabbedTextExtent) вычисляет в логических единицах ширину заданной строки с учетом текущего шрифта. Пример использования GetTextExtent – вычисление ширины промежутка между словами, чтобы равномерно распределить текст по заданной ширине. Допустим, надо вывести строку в участке шириной nWidth. Для выравнивания строки по обеим границам можно использовать следующие вызовы:
Второй параметр SetTextJustification задает число символов-разделителей в строке. По умолчанию символом-разделителем является пробел. После вызова SetTextJustification, все последующие вызовы TextOut и других текстовых функций будут распределять пространство, заданное первым параметром SetTextJustification', равномерно между всеми символами-разделителями.
Шрифты GDI и класс CFont Все текстовые функции-члены CDC пользуются текущим шрифтом, выбранным в контексте устройства. Шрифт – это набор символов определенного размера (высоты) и начертания, у которых есть общие свойства, например, толщина символа (нормальная или жирная). В типографии размер шрифта измеряется в специальных единицах – пунктах. 1 пункт примерно равен 1/72 дюйма. Высота символа шрифта 12 пт равна примерно 1/6 дюйма, но в Windows реальная высота несколько зависит от свойств устройства вывода. Термин "начертание" определяет общий стиль шрифта. Например, Times New Roman и Courier New являются различными начертаниями. Шрифт – один из типов объектов модуля GDI. В MFC для работы со шрифтами есть класс CFont. Сначала надо создать объект этого класса, а затем с помощью одной из его функций-членов CreateFont, CreateFontIndirect, CreatePointFont или CreatePointFontIndirect создать шрифт в модуле GDI. Функциям CreateFont и CreateFontIndirect можно задавать размер шрифта в пикселах, а CreatePointFont и CreatePointFontIndirect – в пунктах. Например, для создания 12-пунктного экранного шрифта Times New Roman функцией CreatePointFont надо выполнить вызовы (размер задается в 1/10 пункта):
Сделать то же самое с помощью CreateFont несколько сложнее, т.к. требуется узнать, сколько в контексте устройства логических единиц приходится на один дюйм по вертикали и затем перевести высоту из пунктов в пикселы:
Среди множества параметров CreateFont есть толщина, признак курсива и др свойства. Эти же свойства шрифта можно хранить в специальной структуре LOGFONT и передавать ее для создания шрифта в CreatePointFontIndirect, например:
Если вы попытаетесь создать шрифт, не установленный в системе, то GDI попробует подобрать наиболее похожий шрифт из установленных. Хотя внутренний механизм преобразования шрифтов GDI и пытается это сделать, не всегда результаты получаются хорошими. Но, по крайней мере, текст на экран выводиться будет.
Стандартные объекты GDI В Windows есть набор предопределенных часто используемых перьев, кистей, шрифтов и других объектов GDI, которые не надо создавать, а можно использовать уже готовые. Они называются стандартными объектами GDI (табл. 5.8). Их можно выбирать в контексте устройства с помощью функции CDC::SelectStockObject или присваивать их существующим объектам CPen, CBrush, и др. с помощью CGdiObject::CreateStockObject. Класс CGdiObject является базовым классом для CPen, CBrush, CFont и других MFC-классов, представляющих объекты GDI. Таблица 5.8. Часто используемые стандартные объекты GDI
Допустим, требуется нарисовать светло-серый круг без контура. Это можно сделать двумя способами, во-первых:
Т.к. прозрачное перо и светло-серая кисть есть среди стандартных объектов GDI, ту же фигуру можно нарисовать так:
Удаление объектов GDI Перья, кисти и другие объекты GDI занимают не только память программы, но и служебную память GDI, объем которой ограничен. Поэтому крайне важно удалять объекты GDI, которые больше не нужны. При автоматическом создании объектов CPen, CBrush, CFont и др. подклассов CGdiObject соответствующие объекты GDI автоматически удаляются из деструкторов этих классов. Если же объекты CGdiObject создавались динамически оператором new, то обязательно надо вызывать для них оператор delete. Явно удалить объект GDI, не уничтожая объект CGdiObject, можно вызовом функции CGdiObject::DeleteObject. Стандартные объекты GDI, даже "созданные" функцией CreateStockObject, удалять не надо. Visual C++ может автоматически отслеживать объекты GDI, которые вы забыли удалить. Для этого применяется перегрузка оператора new. Чтобы разрешить такое слежение в конкретном исходном файле, после директивы включения заголовочного файла Afxwin.h надо добавить директиву определения макроса:
После завершения работы приложения номера строк и имена файлов, содержащие не удаленные объекты GDI, будут показаны в отладочном окне Visual C++. Для удаления объектов GDI важно знать, что нельзя удалить объект, который выбран в контексте устройства. Следующий пример является ошибочным:
Ошибка заключается в том, что объект CPaintDC создается раньше CBrush. Т.к. оба объекта созданы автоматически, и CBrush – вторым, то его деструктор будет вызван первым. Следовательно, соответствующая кисть GDI будет удаляться до того, как будет удален объект dc. Эта попытка будет неудачной. Вы можете исправить положение, если создадите кисть первой. Но везде соблюдать подобное правило в программе тяжело, и очень утомительно искать такие ошибки. В GDI нет функции для отмены выбора объекта в контексте, вроде UnselectObject. Решение заключается в том, чтобы перед удалением объекта CPaintDC выбрать в нем другие объекты GDI, например, стандартную кисть GDI. Многие программисты поступают по-другому: при первом выборе в контексте устройства собственного объекта GDI сохраняют указатель на предыдущий объект, который возвращается функцией SelectObject. Затем, перед удалением контекста, в нем выбираются те объекты, которые были в нем "по умолчанию". Например:
Способ с использованием стандартных объектов GDI реализуется так:
При динамическом создании объектов GDI нельзя забывать про оператор delete:
Резюме Чтобы обеспечить доступ к устройствам графического вывода одновременно нескольким программам, в Windows применяется специальный системный механизм – контекст устройства. Все операции рисования приложения выполняют с помощью контекста устройства. Это служебная структура, в которой хранятся все характеристики конкретного устройства, необходимые модулю GDI для рисования пикселей и графических примитивов. Контекст устройства в MFC представлен классом CDC, от которого унаследованы подклассы для разновидностей контекстов устройств Windows, например, CPaintDC, CClientDC, CWindowDC. Приложение при вызове функций рисования указывает координаты примитивов в логической системе координат. Соответствие между логической системой координат контекста устройства и физической системой координат, связанной с поверхностью изображения, задается режимом преобразования координат. В физической системе координат устройства расстояния измеряются в пикселах. Точка (0, 0) всегда располагается в левом верхнем углу поверхности отображения, ось x направлена вправо, а y – вниз. У логической системы координат эти параметры могут быть другими. Начало координат можно разместить в любом месте поверхности изображения, можно изменить ориентацию осей и масштаб (этим управляет режим преобразования координат). Функции рисования GDI условно делятся на несколько групп: рисование отрезков и кривых, рисование замкнутых фигур, отображение текста и др. Полный список функций рисования есть в разделе справочной системе Visual C++ по классу CDC, в котором эти функции оформлены в виде функций-членов. При рисовании графических примитивов свойства отображения, например, цвет и стиль линии, задаются параметрами контекста устройства, среди которых наиболее важные – текущие выбранные объекты GDI (перо для рисования линий, кисть для заполнения областей, шрифт для вывода текста). Все классы-объекты GDI в MFC унаследованы от базового класса CGdiObject: CPen для перьев, CBrush для кистей, CFont для шрифтов. В каждом классе хранится дескриптор объекта GDI (в переменной-члене m_hObject). Созданные программистом объекты GDI необходимо удалять. Перед удалением надо выбрать в контексте другой объект, т.к. текущий выбранный объект GDI удалить нельзя.
Упражнения 1) Попробуйте выполнить примеры рисования, приведенные в лекции, подставляя фрагменты исходного текста в обработчик OnPaint приложения Hello (оно было рассмотрено в предыдущей лекции). 2) Изучите англо-русский словарь терминов по теме 5-й лекции (см. CD-ROM). 3) Выполните лабораторную работу №2, "Работа с модулем GDI" (см. CD-ROM).
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Последнее изменение этой страницы: 2016-08-01; просмотров: 289; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.119.142.210 (0.014 с.) |