Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Programming_Windows_95_Part_I.pdf
Скачиваний:
96
Добавлен:
05.06.2014
Размер:
4.61 Mб
Скачать

151

Заглянем внутрь

Программа EMF2, приведенная на рис. 4.32, строит дисковый метафайл.

EMF2.MAK

#--------------------

# EMF2.MAK make file

#--------------------

emf2.exe : emf2.obj

$(LINKER) $(GUIFLAGS) -OUT:emf2.exe emf2.obj $(GUILIBS)

emf2.obj : emf2.c

$(CC) $(CFLAGS) emf2.c

EMF2.C

/*-------------------------------------

EMF2.C -- Enhanced Metafile Demo #2

(c) Charles Petzold, 1996

-------------------------------------*/

#include <windows.h>

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

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)

{

static char szAppName[] = "EMF2";

HWND

hwnd;

MSG

msg;

WNDCLASSEX

wndclass;

wndclass.cbSize

= sizeof(wndclass);

wndclass.style

= CS_HREDRAW | CS_VREDRAW;

wndclass.lpfnWndProc

= WndProc;

wndclass.cbClsExtra

= 0;

wndclass.cbWndExtra

= 0;

wndclass.hInstance

= hInstance;

wndclass.hIcon

= LoadIcon(NULL, IDI_APPLICATION);

wndclass.hCursor

= LoadCursor(NULL, IDC_ARROW);

wndclass.hbrBackground

=(HBRUSH) GetStockObject(WHITE_BRUSH);

wndclass.lpszMenuName

= NULL;

wndclass.lpszClassName

= szAppName;

wndclass.hIconSm

= LoadIcon(NULL, IDI_APPLICATION);

RegisterClassEx(&wndclass);

hwnd = CreateWindow(szAppName, "Enhanced Metafile Demo #2", WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL);

ShowWindow(hwnd, iCmdShow);

UpdateWindow(hwnd);

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

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return msg.wParam;

}

152

LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)

{

 

HDC

hdc, hdcEMF;

HENHMETAFILE

hemf;

PAINTSTRUCT

ps;

RECT

rect;

switch(iMsg)

{

case WM_CREATE:

hdcEMF = CreateEnhMetaFile(NULL, "emf2.emf", NULL, "EMF2\0EMF Demo #2\0");

Rectangle(hdcEMF, 100, 100, 200, 200);

MoveToEx

(hdcEMF, 100, 100, NULL);

LineTo

(hdcEMF, 200, 200);

MoveToEx

(hdcEMF, 200, 100, NULL);

LineTo

(hdcEMF, 100, 200);

hemf = CloseEnhMetaFile(hdcEMF); DeleteEnhMetaFile(hemf);

return 0;

case WM_PAINT:

hdc = BeginPaint(hwnd, &ps);

GetClientRect(hwnd, &rect);

rect.left

=

 

rect.right

/ 4;

rect.right

=

3

* rect.right

/ 4;

rect.top

=

 

rect.bottom / 4;

rect.bottom =

3

* rect.bottom / 4;

hemf = GetEnhMetaFile("emf2.emf");

PlayEnhMetaFile(hdc, hemf, &rect);

DeleteEnhMetaFile(hemf);

EndPaint(hwnd, &ps); return 0;

case WM_DESTROY: PostQuitMessage(0); return 0;

}

return DefWindowProc(hwnd, iMsg, wParam, lParam);

}

Рис. 4.32 Программа EMF2

Обратите внимание, что первый параметр функции CreateEnhMetaFile — это описатель контекста устройства. GDI использует этот параметр для вставки метрической информации в заголовок метафайла. Если этот параметр установлен в NULL, то GDI берет эту метрическую информацию из контекста устройства дисплея.

Второй параметр функции CreateEnhMetaFile — это имя файла. Если вы установите этот параметр в NULL (как в программе EMF1), то функция построит метафайл в памяти. Программа EMF2 строит дисковый метафайл с именем EMF2.EMF.

Третий параметр функции — адрес структуры типа RECT, описывающей общие размеры метафайла. Эта часть важнейшей информации (та, что отсутствовала в предыдущем формате метафайлов Windows) заносится в заголовок метафайла. Если вы установите этот параметр в NULL, то GDI определит размеры за вас. Приятно, что

153

операционная система делает это для нас, поэтому имеет смысл устанавливать этот параметр в NULL. Если производительность вашего приложения критична, то вы можете использовать этот параметр для того, чтобы избежать лишней работы GDI.

Наконец, последний параметр — текстовая строка, описывающая метафайл. Эта строка делится на две части: Первая часть — имя приложения (не обязательно имя программы), за которым следует NULL-символ. Вторая часть описывает визуальный образ. Эта часть завершается двумя NULL-символами. Например, используя нотацию языка C ‘\0’ для NULL-символа, можно получить строку описания следующего вида "HemiDemiSemiCad V6.4\0Flying Frogs\0\0". Поскольку C обычно помещает NULL-символ в конец строки, заданной в кавычках, вам нужен только один символ ‘\0’ в конце строки, как показано в программе EMF2.

После создания метафайла программа EMF2 работает также, как программа EMF1, вызывая несколько функций GDI и используя описатель контекста устройства, возвращенный функцией CreateEnhMetaFile. Эти функции рисуют прямоугольник и две линии, соединяющие его противоположные вершины. Затем программа вызывает функцию CloseEnhMetaFile для уничтожения описателя контекста устройства и получения описателя сформированного метафайла.

Затем, еще при обработке сообщения WM_CREATE, программа EMF2 делает то, чего не делала программа EMF1: сразу после получения описателя метафайла программа вызывает функцию DeleteEnhMetaFile. Этот вызов освобождает все ресурсы памяти, необходимые для построения метафайла. Однако дисковый метафайл сохраняется. (Если вы когда-нибудь захотите избавиться от этого файла, то используйте обычные функции удаления файлов.) Обратите внимание, что описатель метафайла не запоминается в статической переменной, как в программе EMF1, поскольку не требуется его сохранение в промежутке времени между обработкой различных сообщений.

Теперь, для использования созданного метафайла программе EMF2 необходимо получить доступ к дисковому файлу. Она делает это при обработке сообщения WM_PAINT путем вызова функции GetEnhMetaFile. Единственный параметр этой функции — имя метафайла. Функция возвращает описатель метафайла. Программа EMF2 передает этот описатель в функцию PlayEnhMetaFile, так же как программа EMF1. Изображение из метафайла выводится в прямоугольник, заданный последним параметром функции. Но в отличие от программы EMF1, программа EMF2 удаляет метафайл перед завершением обработки сообщения WM_PAINT. При обработке последующих сообщений WM_PAINT программа EMF2 опять получает метафайл, проигрывает его и потом удаляет.

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

Поскольку программа EMF2 оставляет не удаленным дисковый метафайл, вы можете взглянуть на него. Он состоит из записей переменной длины, описываемых структурой ENHMETARECORD, определенной в заголовочных файлах Windows. Расширенный метафайл всегда начинается с заголовка типа структуры

ENHMETAHEADER.

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

GetEnhMetaFileHeader(hemf, cbSize, &emh);

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

Заголовочная запись завершается двумя структурами типа SIZE, содержащими два 32-разрядных поля, szlDevice и szlMillimeters. Поле szlDevice хранит размеры устройства вывода в пикселях, а поле szlMillimeters хранит размеры устройства вывода в миллиметрах. Эти данные основываются на контексте устройства, описатель которого передается в функцию CreateEnhMetaFile первым параметром. Если этот параметр равен NULL, то GDI использует экран дисплея. GDI получает метрические данные с помощью функции GetDeviceCaps.

Вывод точных изображений

Большой плюс изображений, хранящихся в виде метафайлов, состоит в том, что они могут растягиваться до любого размера и при этом оставаться правильными. Увеличение или сжатие изображения — это просто масштабирование всех координатных точек, определяющих примитивы. С другой стороны, битовые образы могут терять правильность изображения при сжатии в результате отбрасывания целых строк или столбцов пикселей.

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

Соседние файлы в предмете Операционные системы