Основы графического вывода

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

Рубрика Программирование, компьютеры и кибернетика
Вид лекция
Язык русский
Дата добавления 24.06.2009
Размер файла 498,8 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Метафайл можно рассматривать как специфичное записывающее устройство, которое запоминает все функции GDI, которые выполняются над ним. То есть, когда вы пытаетесь, скажем, нарисовать эллипс, метафайл запомнит команду для рисования эллипса в данном месте и данного размера. Позже вы сможете с помощью специальной функции осуществить воспроизведение метафайла на требуемом контексте устройства.

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

В какой-то степени можно сравнить метафайл с микропрограммой, осуществляющей вывод изображения. Однако это весьма специфичная программа. Для того, что бы оценить область применения метафайлов, надо рассмотреть их основные особенности. Для этого сравним метафайл с битмапом. Конечно эти сравнения весьма относительны, всегда можно придумать такой случай, когда оценки окажутся совершенно неверными:

метафайл компактнее битмапов

время отображения битмапов меньше времени воспроизведения метафайла

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

при изменении размера битмапа возможно существенное снижение качества изображения, метафайл менее чувствителен к этому

разработка метафайла отличается некоторыми особенностями, так как не все функции GDI могут быть использованы с метафайлами.

Полезно, кроме того, узнать, каких вещей сделать с помощью метафайла невозможно:

Метафайл не может использовать переменных. Запоминается выполняемая функция GDI не с выражениями, использованными для вычисления аргументов, а с их численными значениями. При записи метафайла сохраняется список вызываемых функций GDI с использованными числовыми значениями аргументов. Чему они соответствуют, выяснится при воспроизведении метафайла.

Метафайл не сохраняет никаких GDI функций, начинающихся со слова Get... более того, метафайл не выполняет никаких действий, связанных с возвращением информации в программу -- так как во время воспроизведения метафайла многих переменных может не быть, или они могут быть по другим адресам.

Метафайл не использует функций, ссылающихся на него как на реальный контекст устройства: CreateCompatibleDC, ReleaseDC, DeleteDC, CreateCompatibleBitmap, CreateDiscardableBitmap, PlayMetaFile (имеется в виду что на одном метафайле нельзя воспроизвести другой На практике воспроизведение одного метафайла на другом выполняется успешно. Однако, коль скоро Microsoft советует так не делать, то лучше и не пытаться -- вполне может оказаться так, что последующие версии Windows перестанут выполнять эту операцию.).

С метафайлами не работают также функции: GrayString, DrawIcon, SetBrushOrg, FillRect, FrameRect.

Однако не все ограничения метафайла являются непреодолимыми, многие из них легко обходятся. Например, мы хотим с помощью метафайла выводить изображение, занимающее все окно. При создании метафайла мы предположим, что изображение размещается в прямоугольнике, скажем, 100 x 100 единиц. Таким образом созданный метафайл будет воспроизводить изображение в области 100 x 100, независимо от размеров окна; но перед воспроизведением метафайла мы можем выбрать собственную систему координат такой, что бы размер внутренней области окна в этой системе координат был равен 100 x 100, и тогда изображение займет все окно.

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

А как можно работать с метафайлом? Сначала метафайл должен быть создан -- это делается с помощью функции:

HDC CreateMetaFile (lpszFileName);

HDC CreateEnhMetaFile (hdcRef, lpszFileName, lprectBound, lpszDescription); 1

Данная функция создает контекст устройства, связанный с метафайлом. Параметр lpszFileName указывает имя файла, в который будет происходить запись команд. Здесь надо ввести дополнительное понятие. Метафайлы разделяют на метафайлы, использующие диск (файл) для записи команд (disk-based), и метафайлы, использующие блок памяти (memory-based) для хранения набора команд. Если вы указали имя создаваемого файла, то создается метафайл, использующий диск. Однако в качестве lpszFileName может быть указан NULL, тогда будет создан метафайл, использующий память.

Функция CreateEnhMetaFile создает метафайл в формате Win32, обладающий несколько большими возможностями, чем обычный. В частности в заголовке метафайла будет сохранена информация о размерах записанного (параметр lprectBound) в нем изображения и о разрешающей способности устройства (параметр hdcRef), для которого метафайл создан. Помимо этого в заголовок включается небольшая строка, поясняющая название сохраненного рисунка и название приложения, осуществившего запись этого рисунка (параметр lpszDescription). При вызове функции CreateEnhMetaFile допускается задавать нулевые значения hdcRef (по умолчанию будут использованы характеристики дисплея) и lprectBound (размер изображения будет вычисляться в процессе записи рисунка).

Создаваемые этими функциями метафайлы -- разные объекты, так что для работы с метафайлами Win32 необходимо использовать свой набор функций, а для работы с метафайлами Windows 3.x -- свой. В именах функций, работающих с метафайлами Win32 как правило присутствует текст ...EnhMetaFile.

В процессе записи метафайла Win32 можно задать текст комментария:

BOOL GdiComment (hdcEnhMF, cbSize, lpData);

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

HMETAFILE CloseMetaFile (hdcMetaFile);

HENHMETAFILE CloseEnhMetaFile (hdcEnhMetaFile); 1

При этом уничтожается связанный с метафайлом контекст устройства и возвращается хендл метафайла, который может использоваться для его воспроизведения. Этот метафайл является объектом GDI, так что надо очень внимательно следить за удалением этого объекта. В отличие от большинства объектов GDI вместо функции DeleteObject должна быть использована функция:

BOOL DeleteMetaFile (hMF);

BOOL DeleteEnhMetaFile (hEnhMF); 1

Где hMF (hEnhMF) -- хендл метафайла (а не контекста устройства). При этом метафайл как объект GDI уничтожается, а файл, содержащий его, остается на диске. Если вы хотите удалить и этот файл тоже, то либо воспользуйтесь функцией для удаления файлов стандартной библиотеки времени выполнения, например unlink, либо функцией Win32 API DeleteFile.

Если вы уже записали метафайл на диск, то вы можете легко создать объект GDI, соответствующий этому метафайлу с помощью функции:

HMETAFILE GetMetaFile (lpszFileName);

HENHMETAFILE GetEnhMetaFile (lpszFileName); 1

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

HMETAFILE SetMetaFileBits (HGLOBAL hGMemMetaFile);

HMETAFILE SetMetaFileBitsBetter (HGLOBAL hGMemMetaFile);

HENHMETAFILE SetEnhMetaFileBits (cbBuffer, lpData); 1

HENHMETAFILE SetWinMetaFileBits (cbBuffer, lpData, hdcRef, lpMETAFILEPICT); 1

Операции SetMetaFileBits и SetMetaFileBitsBetter возвращают хендл метафайла, созданного из данных, содержащихся в глобальном блоке памяти. Этот метафайл, естественно, является метафайлом, использующим память. Причем исходный блок после создания метафайла нельзя уничтожать или использовать, так как Windows будет использовать его непосредственно.

Функция SetMetaFileBitsBetter отличается от SetMetaFileBits тем, что делает "хозяином" глобального блока, не ваше приложение, а GDI. Таким образом этот объект может использоваться буфером обмена или средствами OLE, так как он не уничтожается при завершении работы вашего приложения. Однако при этом уже вы сами обязаны проследить за тем, что бы в итоге освободить все занятые ресурсы.

Операция SetEnhMetaFileBits создает метафайл из блока данных, заданного его размером и указателем. Функция SetWinMetaFileBits создает метафайл Win32 из данных, подготовленных для метафайла Windows 3.x.

Возможна и обратная операция -- преобразовать метафайл в блок глобальной памяти. Это делается с помощью функции:

HGLOBAL GetMetaFileBits (hMF);

UINT GetEnhMetaFileBits (hEnhMF, cbBuffer, lpBuffer); 1

UINT GetWinMetaFileBits (hEnhMF, cbBuffer, lpBuffer, int nMapMode, hdcRef); 1

После вызова функции GetMetaFileBits нельзя использовать hMF, он считается уничтоженным, но зато вы можете использовать возвращенный хендл блока глобальной памяти. Так вы можете узнать размер метафайла, сохранить его на диске и т.д.

Функция GetEnhMetaFileBits в отличие от GetMetaFileBits не уничтожает метафайла, так что вы сами должны будете позаботиться об его уничтожении. Функция GetWinMetaFileBits кроме того записывает полученные данные в старом формате.

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

HMETAFILE CopyMetaFile (hMF, lpszFileName);

HENHMETAFILE CopyEnhMEtaFile (hEnhMF, lpszFileName); 1

которая скопирует данные метафайла из памяти в дисковый файл с заданным именем. После копирования можно закрыть исходный метафайл с помощью функции DeleteMetaFile (DeleteEnhMetaFile 1).

Для воспроизведения метафайла предназначена функция

BOOL PlayMetaFile (hDC, hMF);

BOOL PlayEnhMetaFile (hDC, hEnhMF, lpRect); 1

которая проигрывает указанный параметром hMF метафайл на заданном контексте устройства hDC.

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

BOOL EnumMetaFile (hDC, hMF, lpfnMFEnumProc, lParam);

BOOL EnumEnhMetaFile (hDC, hEnhMF, lpfnEnhMFEnumProc, lParam, lpRect); 1

Эта функция перебирает все записи метафайла hMF (hEnhMF) и для каждой из них вызывает функцию, заданную указателем lpfnMFEnumProc (lpfnEnhMFEnumProc). Параметр hDC указывает контекст устройства, на котором должен воспроизводиться метафайл, а lParam произвольные данные, которые вы решите передать в функцию lpfnMFEnumProc (lpfnEnhMFEnumProc). В случае Windows API параметр lpfnMFEnumProc должен быть не указателем на саму функцию, а указателем, возвращенным функцией MakeProcInstance; при этом после перебора всех записей метафайла (то есть после возврата из EnumMetaFile) вы должны уничтожить созданный указатель с помощью функции FreeProcInstance; в случае Win32 API надо передавать непосредственно указатель на требуемую функцию.

Функция, которая вызывается для обработки каждой записи метафайла должна иметь следующий вид:

int CALLBACK _export MFEnumProc (

HDC hDC, LPHANDLETABLE lpHTable, LPMETARECORD lpMR, int cHandles, LONG lParam){...}

Или, в случае Win32 API:

int EnhMFEnumProc (// 1

HDC hDC, HANDLETABLE FAR* lpHTable, ENHMETARECORD *lpMR, int cHandles, LONG lParam){...}

Когда Windows вызывает эту процедуру, параметр hDC указывает хендл контекста устройства, на котором воспроизводиться метафайл. Параметр lpHTable является указателем на таблицу хендлов объектов GDI, созданных при воспроизведении метафайла. Причем параметр cHandles указывает число объектов в этой таблице. Параметр lpMR является указателем на структуру, описывающую ту запись метафайла, которая должна воспроизводиться, а параметр lParam содержит те данные, которые вы передали через одноименный параметр функции EnumMetaFile.

Функцию MFEnumProc вы должны написать сами. В простейшем случае она может состоять из единственного вызова функции:

void PlayMetaFileRecord (hDC, lpHTable, lpMR, cHandles);

void PlayEnhMetaFileRecord (hDC, lpHTable, lpMR, cHandles); 1

Которая осуществит воспроизведение данной записи метафайла. Однако до, после или вместо этого вы можете проанализировать запись метафайла и выполнить нужные действия. Вы можете даже изменять запись, причем эти изменения сохраняются в метафайле.

Итак, что содержится в записи?

typedef struct tagMETARECORD {

DWORD rdSize;

UINT rdFunction;

UINT rdParm[ 1 ];

} METARECORD;

typedef struct tagENHMETARECORD {// 1

DWORD iType;

DWORD nSize;

DWORD dParm[ 1 ];

} ENHMETARECORD;

Поле rdSize указывает полный размер записи метафайла, включая заголовок, в словах (то есть реально его надо умножать на 2, что бы получить размер в байтах).

Поле rdFunction задает номер выполняемой функции GDI. Эти номера вы можете посмотреть в windows.h, они начинаются с префикса META_ (например META_RECTANGLE). Младший байт этого слова содержит номер функции GDI, а старший -- размер передаваемых этой функции аргументов, выраженный в словах.

Массив rdParm является массивом данных, передаваемых функции GDI. Данные перечислены в обратном порядке, по сравнению с тем, как они размещены в описании функции. Если при этом функция содержит указатель на что-либо (например TextOut содержит указатель на текст), то этот объект целиком включается в запись на месте соответствующего аргумента.

В случае Win32 поля несколько иные: iType задает «тип записи», то есть номер функции, которые имеют префикс EMR_, вместо META_ (например EMR_SETMAPMODE), поле nSize задает размер непосредственно в байтах, а dParm -- параметры записи.

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


Подобные документы

  • Разработка графического редактора для рисования двухмерной и трехмерной графики, используя язык программирования Java и интерфейсы прикладного программирования Java 2D и Java 3D. Создание графического редактора 3D Paint. Основные методы класса Graphics.

    курсовая работа [197,5 K], добавлен 19.11.2009

  • Сущность, задачи и особенности объектно-ориентированного программирования. Создание и редактирование графических файлов при помощи различных инструментов рисования. Основные требования к аппаратному и программному обеспечению. Руководство пользователя.

    курсовая работа [270,9 K], добавлен 09.03.2009

  • Структура организации графического интерфейса, объявление и создание слушателей событий с помощью анонимных классов. Представление данных для таблицы – класс AbstractTableModel. Визуализация ячеек таблицы. Два основных типа потоков ввода-вывода в Java.

    лекция [685,3 K], добавлен 01.05.2014

  • Разработка графического интерфейса для ввода начальных значений, отображения результатов и тестирования методов собственного класса на языке программирования С++. Подсветка цветом выбранных операндов в процессе их инициализации и вывода на дисплей.

    курсовая работа [234,6 K], добавлен 27.12.2014

  • Изучение особенностей растровых и векторных графических редакторов. Создание графического редактора: выбор языка программирования, разработка структуры программы и алгоритма работы. Описание интерфейса программы. Руководство программиста и пользователя.

    курсовая работа [1,3 M], добавлен 28.07.2013

  • Растровая и векторная графика. Растровые графические редакторы. Масштабирование растрового изображения. Средства хранения высокоточных графических объектов. Изменение масштаба без потери качества и практически без увеличения размеров исходного файла.

    презентация [652,8 K], добавлен 11.03.2015

  • Растровая графика, составление графических изображений из отдельных точек (пикселей). Растровые графические редакторы. Векторная графика - построение изображения из простых объектов. Достоинства, недостатки и применение растровой и векторной графики.

    презентация [7,8 K], добавлен 06.01.2014

  • Определение понятия "видеокарта". Рассмотрение режима работы устройства по преобразованию цифрового сигнала в аналоговый электрический. Изучение особенностей изображения графических и текстовых знаков. Описание графического ускорителя и акселератора.

    презентация [1,2 M], добавлен 20.12.2015

  • Методы вывода графических примитивов в программе Delphi. Основные методы, объявленные в классе TCanvas. Использование объектов Brush, Pen, Front. Примеры применения функции Round Rect. Отличия способов рисования прямоугольника Polyline и Polygon.

    курсовая работа [834,1 K], добавлен 17.09.2014

  • Создание с помощью графического редактора логотипа и баннера для образовательного сайта "Областные математические олимпиады". Типы логотипов, баннер как графический элемент страницы сайта. Обзор инструментов графического редактора Adobe Illustrator.

    курсовая работа [2,9 M], добавлен 08.02.2014

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.