MORE INFORMATION
The following file is available for download from the Microsoft Download Center:
For additional information about how to download Microsoft Support files, click the following article number to view the article in the Microsoft Knowledge Base:
119591 How to Obtain Microsoft Support Files from Online Services
Microsoft scanned this file for viruses. Microsoft used the most current virus-detection software that was available on the date that the file was posted. The file is stored on security-enhanced servers that help to prevent any unauthorized changes to the file.
Creating the Enhanced Metafile
An enhanced metafile is created with a call to
CreateEnhMetaFile().
CreateEnhMetaFile() is declared as follows:
HDC CreateEnhMetaFile( HDC hdcRef, LPCTSTR lpFilename,
CONST RECT *lpRect, LPCTSTR lpDescription );
Following are the parameters to this call:
hdcRef is a reference DC and provides some crucial reference information
for the construction of the metafile. The resolutions in both pixels and
millimeters are taken from this device, and all font metrics are based on
this DC. For the best possible reproduction on all output devices, it is a
good idea to choose a high resolution device for the reference device.
Otherwise, some grainyness may appear if the output device is of
considerably higher resolution than the reference device.
lpFileName is the name of the file that will contain the metafile. If this
parameter is NULL, the metafile is a memory metafile and is not stored on
disk.
lpRect is a rectangle that specifies the dimensions in 0.01 mm units of the
virtual metafile device. This rectangle is stored in the metafile and can
be retrieved at play time to determine the desired real size of the output.
Although no clipping is performed for this rectangle, some metafile players
may presume that the image in the metafile fits in the rectangle.
lpDescription simply provides a way to store the name of the application
that created the metafile as well as a description of the contents in the
form of two NULL-terminated strings, terminated with an additional NULL as
in this example:
App\0Description\0\0
App is the name of the application that created the metafile and
Description is a description of the image.
The Metafile Device
The metafile device has a real size defined by the lpRect parameter in 0.01
mm units. The number of device units on the metafile can be determined by
using the pixel/mm ratio of the reference DC and the metafile device size
given in the lpRect parameter. For example:
MetaPixelsX = MetaWidthMM * MetaPixels / (MetaMM * 100);
where MetaPixelsX = number of pixels on the X axis
MetaWidthMM = metafile width in 0.01mm units
MetaPixels = width in pixels of the reference device
MetaMM = width in millimeters of the reference device
A similar calculation can be used to determine the number of pixels in the
Y direction of the metafile device.
Note that although the metafile device has a real size, it does not clip
output to that region. It is entirely possible to record drawing commands
that have output outside of the metafile device surface.
Playing the Enhanced Metafile
The metafile device provides only half of the mapping from metafile space
to target device space. The other half is provided by the RECT passed to
the
PlayEnhMetaFile() call. It specifies a play rectangle in which to play the metafile and is specified in logical coordinates on the target device context. The metafile device rectangle is mapped to this play rectangle. This provides the scalability of enhanced metafiles; adjusting the play rectangle adjusts the size of the output. No clipping is performed on the play rectangle.
So, neither the metafile device nor the play rectangle perform clipping.
This means that if any drawing commands were recorded to occur outside the
metafile device, they will be shown outside the play rectangle when the
metafile is played. This mapping is illustrated in the Sample1.emf sample
enhanced metafile.
If the goal is to play the metafile at its true size, the size of the
original metafile device can be determined by a call to
GetEnhMetaFileHeader(). This call fills in an
ENHMETAHEADER structure, of which the rclFrame member specifies the metafile device rectangle in 0.01 mm units. That rectangle can be translated into logical units for the target DC and used as the lpRect parameter for
PlayEnhMetaFile(). The
PlayEnhMetaFileAtOriginalSize() function in the sample demonstrates this.
Mapping Modes
During the recording of the metafile, the mapping mode, window extents and
origin, and viewport extents and origin combine to map logical units to
device units on the metafile device. As with a normal DC, the window
extents and origin define the logical space, while the viewport extents and
origin are relative to the metafile device units described above.
For example: The following code creates an enhanced metafile that is
dwInchesX wide by dwInchesY tall with dwDPI logical Dots Per Inch (DPI):
HDC MyCreateEnhMetaFile( LPTSTR szFileName, // Metafile filename
DWORD dwInchesX, // Width in inches
DWORD dwInchesY, // Height in inches
DWORD dwDPI ) // DPI (logical units)
{
RECT Rect = { 0, 0, 0, 0 };
TCHAR szDesc[] = "AppName\0Image Description\0\0";
HDC hMetaDC, hScreenDC;
float PixelsX, PixelsY, MMX, MMY;
// dwInchesX x dwInchesY in .01mm units
SetRect( &Rect, 0, 0, dwInchesX*2540, dwInchesY*2540 );
// Get a Reference DC
hScreenDC = GetDC( NULL );
// Get the physical characteristics of the reference DC
PixelsX = (float)GetDeviceCaps( hScreenDC, HORZRES );
PixelsY = (float)GetDeviceCaps( hScreenDC, VERTRES );
MMX = (float)GetDeviceCaps( hScreenDC, HORZSIZE );
MMY = (float)GetDeviceCaps( hScreenDC, VERTSIZE );
// Create the Metafile
hMetaDC = CreateEnhMetaFile(hScreenDC, szFileName, &Rect, szDesc);
// Release the reference DC
ReleaseDC( NULL, hScreenDC );
// Did you get a good metafile?
if( hMetaDC == NULL )
return NULL;
// Anisotropic mapping mode
SetMapMode( hMetaDC, MM_ANISOTROPIC );
// Set the Windows extent
SetWindowExtEx( hMetaDC, dwInchesX*dwDPI, dwInchesY*dwDPI, NULL );
// Set the viewport extent to reflect
// dwInchesX" x dwInchesY" in device units
SetViewportExtEx( hMetaDC,
(int)((float)dwInchesX*25.4f*PixelsX/MMX),
(int)((float)dwInchesY*25.4f*PixelsY/MMY),
NULL );
return hMetaDC;
}
Note that clipping is not performed by the window extents, viewport
extents, or the metafile device. It is possible to draw beyond the window
extents, which will map beyond the viewport extents. Those numbers provide
only a ratio of logical units to metafile device units. Further, it is
possible to have viewport extents that extend beyond the metafile surface.
The drawing is not clipped to the metafile surface. This mapping is
illustrated in the Sample2.emf sample enhanced metafile.
Palettes in Enhanced Metafiles
The
SelectPalette() API can be used to record a palette into an enhanced metafile. That palette can then be retrieved at play-time via the
GetEnhMetaFilePaletteEntries() API. This allows the player to faithfully reproduce palletized images and properly respond to palette messages. The
GetEnhancedMetafilePalette() function in the sample demonstrates extracting a palette from an enhanced metafile.
Note that if multiple palettes were used in recording the metafile, the
palette entries retrieved by
GetEnhMetaFilePaletteEntries()includes
all the entries from all the palettes. If this includes more entries than
the current display can reproduce, it is the player's responsibility to
choose a subset of those colors from which to create the actual palette to
be used during playback.