Операционная система Microsoft Windows 3.1 для программиста. Дополнительные главы

       

Чтение метафайла


Рассмотрим теперь процедуру чтения из Clipboard и отображения в окне метафайла. Эта процедура усложняется необходимостью анализа режима отображения, установленного для метафайла, и необходимостью учета трех способов задания размеров изображения при рисовании (напомним, что размеры могут быть совсем не заданы, заданы в виде ширины и высоты, заданы в виде отношения ширины и высоты).

Открыть Clipboard функцией OpenClipboard (если Clipboard не был открыт ранее при чтении данных в других форматах)

Вызвать функцию GetClipboardData, передав ей через единственный параметр константу CF_METAFILEPICT, и проверить возвращенное значение. Если функция вернула NULL, Clipboard не содержит данных в формате CF_METAFILEPICT. Ненулевое значение является идентификатором блока памяти заголовка метафайла. Этот метафайл можно проиграть в контексте отображения для рисования содержимого Clipboard

Зафиксировать блок памяти заголовка метафайла

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

Расфиксировать блок памяти заголовка метафайла

Закрыть Clipboard функцией CloseClipboard

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

hmf = (HMETAFILE)GetClipboardData(CF_METAFILEPICT); if(hmf != NULL) { lpmfp = (LPMETAFILEPICT)GlobalLock(hmf); if(lpmfp != NULL) { SaveDC(hdc); PrepareMetaFile(hdc, lpmfp, cxClient, cyClient); PlayMetaFile(hdc, lpmfp->hMF); RestoreDC(hdc, -1); GlobalUnlock(hmf); } }

После фиксирования заголовка метафайла приложение сохраняет текущий контекст отображения функцией SaveDC, так как перед проигрыванием метафайла этот контекст будет изменен в соответствии с содержимым полей заголовка метафайла. После проигрывания контекст отображения восстанавливается при помощи функции RestoreDC.

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




Прежде всего, эта функция устанавливает контекст отображения, указанный в заголовке метафайла, вызывая функцию SetMapMode:

void PrepareMetaFile(HDC hdc, LPMETAFILEPICT lpmfp, int cxClient, int cyClient) { int x, y;

SetMapMode(hdc, lpmfp->mm);

if(lpmfp->mm == MM_ISOTROPIC lpmfp->mm == MM_ANISOTROPIC) { if(lpmfp->xExt == 0) SetViewportExtEx(hdc, cxClient, cyClient, NULL);

else if(lpmfp->xExt > 0) { x = lpmfp->xExt; y = lpmfp->yExt; HiMetricToSize(&x, &y); SetViewportExtEx(hdc, x, y, NULL); }

else if(lpmfp->xExt < 0) { x = -lpmfp->xExt; y = -lpmfp->yExt; HiMetricToSizeScaled(&x, &y, cxClient, cyClient); SetViewportExtEx(hdc, x, y, NULL); } } else SetViewportExtEx(hdc, lpmfp->xExt, lpmfp->yExt, NULL); }

Далее для изотропного и анизотропного режимов отображения анализируется содержимое полей xExt и yExt заголовка метафайла с целью выбора размеров изображения в контексте отображения.

Если в заголовке метафайла размеры изображения не указаны (равны нулю), функция PrepareMetaFile устанавливает размер изображения, равным размеру внутренней области окна (размеры окна передаются функции через параметры).

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

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

Исходные тексты функций HiMetricToSize и HiMetricToSizeScaled приведены ниже в разделе "Приложение CLIPSHOW".

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


Содержание раздела