Metafiles

生活百科 2023-01-17 20:14生活百科www.aizhengw.cn

Metafiles

元档案(Metafiles)是一个以设备无关格式存储图像的结构的集合。它可以有效的保持图像的原始尺寸。但它的显示速度没有点阵图快,如果应用程式要求高速的显示速度,并且对设备无关特性要求不是很严的话,应使用点阵图来存储和显示图像。

基本介绍

  • 中文名元档案
  • 外文名Metafiles
  • 类型存储图像的集合
  • 释义一个可变长结构数组

关于元档案

为微软windows作业系统编写的应用程式可以使用两种图像工具来存储图像元档案和点阵图。本节将描述元档案的信息。
在内部,元档案是一个可变长结构数组,称为元档案记录(metafile records)。元档案中的第一个记录描述了一些公共的信息,比如创建图像的设备的解析度、图像的尺寸等等。剩下的记录则是用于描述图像的GDI函式操作记录。当元档案设备描述表(DC)被创建之后,GDI的操作记录就会被存储到元档案中。这个DC是被在创建图像期间所有的绘图操作所需要的。当windows处理一个与元档案DC相关联的GDI函式时,它将转换这个函式到适当的格式并以记录的形式追加(存储)到相关的元档案中。
当图像建立完毕,一个记录也加到元档案中之后,这个元档案就可以採用剪贴簿来传递给其它的应用程式,或是嵌入到其它的档案中、存储到磁碟档案中,也可以用于以后重複显示之用。如果元档案的记录已经转换为设备命令并且已被适当的设备处理了,那幺该元档案已经被显示了(played)。
有两种类型的元档案增强型元档案和Windows型元档案。增强型元档案一般被用于用Win32 API编写的应用程式中。它的格式包括元档案头、GDI目标的句柄表、私有调色板和元档案记录数组。增强型元档案提供真正的设备无关性。
Windows元档案一般用于用Windows version 3.X API编写的应用程式中。这种格式的元档案是由一个元档案头和元档案记录数组组成。Windows元档案在技术上有一定的限制,现在已经很少被使用了—它之所以现在还被支持,只是为了系统的兼容性。

增强型元档案

增强型元档案格式
================
程式设计师可以使用增强型元档案来存储用Win32 GDI函式创建的图像(包括新的路径和转换函式)。因为增强型元档案对于Win32 API是一种标準,以这种格式存储的图像可以从一个Win32应用程式拷贝到另一个应用程式。而且,因为这种格式是真正与设备无关的,所以保证图像的尺寸与形状在其它设备中也保持不变。
增强型元档案
============
增强型元档案是一个记录的数组。而元档案记录是一个可变长的ENHMETARECORD结构。这个结构标识了记录的类型、记录的长度和包含的附加数据。
在增强型元档案中的第一个记录总是增强型元档案头。这个档案头描述了以下信息
元档案的尺寸 (以位元组为单位)
图像的框线尺寸 (设备单位)
图像的框线尺寸 (0.01 mm 为单位)
在元档案中记录的个数
到可选的文本描述的偏移
可选调色板的尺寸
原始设备分辩率 (像素单位)
原始设备分辩率 (mm单位)
可选的文本描述将用于描述图像以及作者的一些信息,它一般放在元档案头的后面。可选的调色板指出了创建增强型元档案所使用的颜色。剩下的记录标识了用于创建图像的GDI函式。下面的範例描述了系统是怎样将GDI函式转换为一个元档案记录的
假设用户调用了SetMapMode(4)这个GDI函式,经系统转换后,它
将变为一个记录存入元档案,记录的内容如下
00000011 0000000C 00000004
其中值00000011指明了记录的类型(11表示GDI函式SetMapMode函式),0C则是这个记录的长度
(以位元组为单位),04标识了入口参数4。
增强型元档案操作
================
程式设计师可以通过提供适当的参数调用CreateEnhMetaFile()函式来创建增强型元档案。Win32 API使用这些参数来维护图像的尺寸,判断元档案是存储于磁碟上还是存储于记忆体中,等等。
要想在输出设备上维护图像的尺寸,Win32 API需要参考设备的分辩率(参考设备是指第一次显示这个元
档案时所在的设备),以及参考DC(就是关联到参考设备上的DC)。当调用CreateEnhMetaFile()函式的
时候,应用程式必需提供一个DC句柄(参考DC),应用程式可以使用GetDC()或CreateDC()函式来获得一
个参考DC,也可以将参考DC指定为NULL,此时系统将当前的显示设备作为参考设备。
大多数应用程式创建元档案图像都会存储到磁碟中,但这并不是必需的。如果应用程式想将图像存储到磁碟中,则它在调用CreateEnhMetaFile()函式时必需提供一个有效的档案名称。如果开发者不提供档案名称,则系统将自动的为其创建一个临时档案,并将元档案存储于记忆体中。
程式设计师也可以加一些描述本图像及作者的一些信息到增强型元档案中。应用程式可以在File Open dialog box(档案打开对话框)中显示这些信息,以给用户一些有益提示。如果应用程式想向增强型元档案中加入一个这样的描述串,则他必需在调用CreateEnhMetaFile()函式时提供一个指向该描述串的指针。
当调用CreateEnhMetaFile()函式成功之后,该函式将返回一个标识元档案的DC句柄。这个DC在与之关联
的档案(或者说是输出设备)上是唯一的。当Windows系统在处理一个GDI函式时,如果它收到的是一个元档案DC句柄,则系统将转换GDI函式为一个增强型元档案记录,并将其追加到增强型元档案的尾部。
当一个记录追加到增强型元档案之后,图像就算绘製完毕。此时,应用程式可以调用
CloseEnhMetaFile()函式来关闭并删除该元档案DC,并返回一个标识增强型元档案的句柄。应用程式可以使用该句柄来完成以下任务
显示存储在增强型元档案中的图像(回放)
创建增强型元档案的拷贝
枚举、编辑、或拷贝增强型元档案中的单个记录
获取增强型元档案中可选的描述文本
获得增强型元档案头的拷贝
获取增强型元档案的二进制版
枚举可选调色板中的颜色
转换增强型元档案格式为Windows元档案格式
应用程式可以使用CopyEnhMetaFile()函式来拷贝增强型元档案,它支持标识增强型元档案的句柄,也支持指向新档案名称的指针。
很多绘图软体或CAD软体都需要编辑存储在增强型元档案中图像的手段。虽然编辑增强型元档案是一项比较複杂的任务,但系统仍提供这种方法。开发者可以使用EnumEnhMetaFile()函式,再结合其它的一些Win32函式就可以对单个的增强型元档案记录进行编辑(该函式有一个回调函式很有用)。
一些应用程式可能需要在FileOpen对话框里显示增强型元档案的文本描述串,此时,程式设计师可以使用
GetEnhMetaFileHeader()函式来获取增强型元档案头,该档案头中的一个成员变数表明了该元档案中是否存在文本描述串。如果该增强型元档案中存在文本描述串,则应用程式可通过调用
GetEnhMetaFileDescription()函式来获取该文本串。
一些应用程式使用GetEnhMetaFileBits()函式来获取元档案的内容,,在获取内容之前,应用程式必需提供档案的尺寸。获取这个尺寸值,可调用GetEnhMetaFileHeader()函式先取得档案头,该档案头中的一个成员变数标识了档案的尺寸。
要想使增强型元档案在不同的输出设备上保持颜色一致,应用程式可以调用CreatePalette()函式来创建调色板,并将其存储到增强型元档案中。其它的程式在显示这个增强型元档案之前,可获取该调色板,并调用RealizePalette()函式来实现该调色板。应用程式可用增强型元档案头中的某个成员的值来判断是否有调色板。如果有,可调用GetEnhMetaFilePaletteEntries()函式来获取这个逻辑调色板。
Windows元档案格式
=================
Win32 API支持Windows元档案主要是为了保持系统向下兼容。以下内容是这种格式的一些技术限制
Windows元档案是与应用程式、特定设备相关的。修改应用程式的映射模式或设备的分辩率,将影响
Windows元档案的回放效果(图像的颜色、尺寸可能会改变)。
Windows元档案头包含的信息不足。它不包含诸如图像的尺寸、创建图像的设备的分辩率、描述文本串、调色板等等信息。
Windows元档案不支持新的曲线、通道、转换函式。
一些Windows元档案记录不能被scaled。
与Windows元档案相关联的元档案DC不能被查询(也就是说,应用程式不能获取该设备的分辩率、字型等等信息)。
要想转换一个Windows元档案到增强型元档案,应用程式可以调用GetMetaFileBitsEx()函式来获取
Windows元档案数据,然后调用SetWinMetaFileBits()函式将数据转换为增强型元档案。
程式设计师在编写Win32应用程式时,应儘量避免使用Windows元档案格式,而应使用增强型元档案格式。
创建一个增强型元档案
====================
下面这节将描述一个範例,用以说明存放到磁碟上的增强型元档案的创建方法。档案名称由用户指定。
範例中使用了应用程式的视窗DC作为元档案的参考DC(Windows将该设备的分辩率数据存储于增强型元文
件头中)。应用程式通过调用GetDC()函式来获取这个DC.
範例使用了应用程式客户区的大小作为图像的框架大小(通过调用GetClientRect()函式来获得)。然后
应用程式转换设备单位为0.01mm单位,并将该值代入CreateEnhMetaFile()函式中。
範例显示储存为对话框,用户可指定新档案的名字。系统将向档案名称子串尾部追加三个字元.EMF作为档案的扩展名。然后将该名字传送给CreateEnhMetaFile()函式。
範例也向增强型元档案中加入了文本描述串,这个描述串是作为资源存放在串表中的。
以下是範例代码
/ Obtain a handle to a reference DC. /
hdcRef = GetDC(hWnd);
/
Determine the picture frame dimensions.
iWidthMM is the display width in millimeters.
iHeightMM is the display height in millimeters.
iWidthPels is the display width in pixels.
iHeightPels is the display height in pixels
/
iWidthMM = GetDeviceCaps(hdcRef, HORZSIZE);
iHeightMM = GetDeviceCaps(hdcRef, VERTSIZE);
iWidthPels = GetDeviceCaps(hdcRef, HORZRES);
iHeightPels = GetDeviceCaps(hdcRef, VERTRES);
/
Retrieve the coordinates of the client
rectangle, in pixels.
/
GetClientRect(hWnd, &rect);
/
Convert client coordinates to .01-mm units.
Use iWidthMM, iWidthPels, iHeightMM, and
iHeightPels to determine the number of
.01-millimeter units per pixel in the x-
and y-directions.
/
rect.left = (rect.left iWidthMM 100)/iWidthPels;
rect.top = (rect.top iHeightMM 100)/iHeightPels;
rect.right = (rect.right iiWidthMM 100)/iWidthPels;
rect.bottom = (rect.bottom iHeightMM 100)/iHeightPels;
/ Load the filename filter from the string table. /
LoadString(hInst, IDS_FILTERSTRING,
(LPSTR)szFilter, sizeof(szFilter));
/
Replace the '%' separators that are embedded
between the strings in the string-table entry
with '\0'.
/
for (i=0; szFilter[i]!='\0'; i++)
if (szFilter[i] == '%')
szFilter[i] = '\0';
/ Load the dialog title string from the table. /
LoadString(hInst, IDS_TITLESTRING,
(LPSTR)szTitle, sizeof(szTitle));
/ Initialize the OPENFILENAME members. /
szFile[0] = '\0';
Ofn.lStructSize = sizeof(OPENFILENAME);
Ofn.hwndOwner = hWnd;
Ofn.lpstrFilter = szFilter;
Ofn.lpstrFile= szFile;
Ofn.nMaxFile = sizeof(szFile);
Ofn.lpstrFileTitle = szFileTitle;
Ofn.nMaxFileTitle = sizeof(szFileTitle);
Ofn.lpstrInitialDir = (LPSTR)NULL;
Ofn.Flags = OFN_SHOWHELP | OFN_OVERWRITEPROMPT;
Ofn.lpstrTitle = szTitle;
/
Display the Filename common dialog box. The
filename specified by the user is passed
to the CreateEnhMetaFile function and used to
store the metafile on disk.
/
GetSaveFileName(&Ofn);
/ Load the description from the string table. /
LoadString(hInst, IDS_DESCRIPTIONSTRING,
(LPSTR)szDescription, sizeof(szDescription));
/
Replace the '%' string separators that are
embedded between strings in the string-table
entry with '\0'.
/
for (i=0; szDescription[i]!='\0'; i++)
if (szDescription[i] == '%')
szDescription[i] = '\0';
/ Create the metafile DC. /
hdcMeta = CreateEnhMetaFile(hdcRef,
(LPTSTR) Ofn.lpstrFile,
&rect, (LPSTR)szDescription);
if (!hdcMeta)
errhandler("CreateEnhMetaFile", hWnd);
/ Release the reference DC. /
ReleaseDC(hWnd, hdcRef);
显示图像并将其存入增强型元档案中
================================
这一节描述元档案图像的创建及存储。範例绘製一个图像到萤幕或元档案。如果给出了显示DC,则函式将
图像绘製到萤幕上,如果给出了元档案DC,则函式将图像绘製到元档案中。
以下是範例代码
void DrawOrStore(HWND hwnd, HDC hdcMeta, HDC hdcDisplay)
{
RECT rect;
HDC hDC;
int fnMapModeOld;
HBRUSH hbrOld;
/ Draw it to the display DC or store it in the metafile DC. /
if (hdcMeta)
hDC = hdcMeta;
else
hDC = hdcDisplay;
/ Set the mapping mode in the DC. /
fnMapModeOld = SetMapMode(hDC, MM_LOENGLISH);
/ Find the midpoint of the client area. /
GetClientRect(hwnd, (LPRECT)&rect);
DPtoLP(hDC, (LPPOINT)&rect, 2);
/ Select a gray brush. /
hbrOld = SelectObject(hDC, GetStockObject(GRAY_BRUSH));
/ Draw a circle with a one inch raduis. /
Ellipse(hDC, (rect.right/2 - 100), (rect.bottom/2 + 100),
(rect.right/2 + 100), (rect.bottom/2 - 100));
/ Perform additional drawing here. /
/ Set the device context back to its original state. /
SetMapMode(hDC, fnMapModeOld);
SelectObject(hDC, hbrOld);
}
打开一个增强型元档案并显示它的内容
==================================
这一节描述了应用程式怎样打开一个存放于磁碟上的增强型元档案,并将元档案图像显示在视窗客户区的方法。
範例通过使用OpenFile对话框来让用户选择一个增强型元档案,并将选择的档案名称发给GetEnhMetaFile()函式,该函式返回一个标识该档案的句柄。这个句柄就可以传给PlayEnhMetaFile()函式来显示元档案图像。
以下是範例代码
LoadString(hInst, IDS_FILTERSTRING,
(LPSTR)szFilter, sizeof(szFilter));
/
Replace occurrences of '%' string separator
with '\0'.
/
for (i=0; szFilter[i]!='\0'; i++)
if (szFilter[i] == '%')
szFilter[i] = '\0';
LoadString(hInst, IDS_DEFEXTSTRING,
(LPSTR)szDefExt, sizeof(szFilter));
/
Use the OpenFilename common dialog box
to obtain the desired filename.
/
szFile[0] = '\0';
Ofn.lStructSize = sizeof(OPENFILENAME);
Ofn.hwndOwner = hWnd;
Ofn.lpstrFilter = szFilter;
Ofn.lpstrCustomFilter = (LPSTR)NULL;
Ofn.nMaxCustFilter = 0L;
Ofn.nFilterIndex = 1L;
Ofn.lpstrFile = szFile;
Ofn.nMaxFile = sizeof(szFile);
Ofn.lpstrFileTitle = szFileTitle;
Ofn.nMaxFileTitle = sizeof(szFileTitle);
Ofn.lpstrInitialDir = (LPSTR) NULL;
Ofn.lpstrTitle = (LPSTR)NULL;
Ofn.Flags = OFN_SHOWHELP | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
Ofn.nFileOffset = 0;
Ofn.nFileExtension = 0;
Ofn.lpstrDefExt = szDefExt;
GetOpenFileName(&Ofn);
/ Open the metafile. /
hemf = GetEnhMetaFile(Ofn.lpstrFile);
/ Retrieve a handle to a window DC. /
hDC = GetDC(hWnd);
/ Retrieve the client rectangle dimensions. /
GetClientRect(hWnd, &rct);
/ Draw the picture. /
PlayEnhMetaFile(hDC, hemf, &rct);
/ Release the metafile handle. /
DeleteEnhMetaFile(hemf);
/ Release the window DC. /
ReleaseDC(hWnd, hDC);
编辑一个增强型元档案
====================
要想编辑存储于增强型元档案中的图像,应用程式必需执行下面的一些任务
1 使用HIT-TESTING去捕捉游标坐标并获取用户想编辑的目标的位置(line, arc, rectangle, ellipse etc.)
2 转换这些坐标为逻辑单位(或全局单位)
3 调用EnumEnhMetaFile()函式,并且检查每一个元档案记录
4 判断给定的记录是否与GDI绘製函式相符合
5 如果符合,则判断元档案中该记录的坐标是否与截获的用户坐标相同。
6 如果坐标也相同,则说明找到了用户想编辑的记录,可在萤幕上清除该目标
7 从元档案中删除这个记录,并保存该记录的地址到一个指针变数中
8 允许用户重画该目标或替换目标
9 转换新绘製的GDI函式为一个或多个增强型元档案的记录
10 保存这些记录到增强型元档案中
元档案函式
==========
下面的函式用于增强型元档案
CloseEnhMetaFile
CopyEnhMetaFile
CreateEnhMetaFile
DeleteEnhMetaFile
EnhMetaFileProc
EnumEnhMetaFile
GdiComment
GetEnhMetaFile
GetEnhMetaFileBits
GetEnhMetaFileDescription
GetEnhMetaFileHeader
GetEnhMetaFilePaletteEntries
GetWinMetaFileBits
PlayEnhMetaFile
PlayEnhMetaFileRecord
SetEnhMetaFileBits
SetWinMetaFileBits
下面的函式为提供系统兼容而被保留
CloseMetaFile
CopyMetaFile
CreateMetaFile
DeleteMetaFile
EnumMetaFile
EnumMetaFileProc
GetMetaFile
GetMetaFileBitsEx
PlayMetaFile
PlayMetaFileRecord
SetMetaFileBitsEx
增强型元档案所用到的结构
========================
结构ENHMETAHEADER
typedef struct tagENHMETAHEADER { // enmh
DWORD iType;
DWORD nSize;
RECTL rclBounds;
RECTL rclFrame;
DWORD dSignature;
DWORD nVersion;
DWORD nBytes;
DWORD nRecords;
WORD nHandles;
WORD sReserved;
DWORD nDescription;
DWORD offDescription;
DWORD nPalEntries;
SIZEL szlDevice;
SIZEL szlMillimeters;
DWORD cbPixelFormat;
DWORD offPixelFormat;
DWORD bOpenGL;
} ENHMETAHEADER;
结构ENHMETARECORD
typedef struct tagENHMETARECORD { // enmr
DWORD iType;
DWORD nSize;
DWORD dParm[1];
} ENHMETARECORD;
结构HANDLETABLE
typedef struct tagHANDLETABLE { // ht
HGDIOBJ objectHandle[1];
} HANDLETABLE;
结构METAHEADER
typedef struct tagMETAHEADER { // mh
WORD mtType;
WORD mtHeaderSize;
WORD mtVersion;
DWORD mtSize;
WORD mtNoObjects;
DWORD mtMaxRecord;
WORD mtNoParameters;
} METAHEADER;
结构METARECORD
typedef struct tagMETARECORD { // mr
DWORD rdSize;
WORD rdFunction;
WORD rdParm[1];
} METARECORD;
上一篇:GP04 下一篇:nat(网路地址转换方法)

Copyright@2015-2025 www.aizhengw.cn 癌症网版板所有