Looking at Metafiles

You can get a good idea of what a metafile is and is not by dumping out the contents of MYLOGO.WMF. The metafile begins with an 18-byte header record. This is followed by a series of metafile records, each of which contains three or more 2-byte words. The first word is the number of words in the record, including the first; the second word is 0; the third word is a code that indicates the GDI call that the record represents.

These codes are documented in Chapter 9 of the Programmer's Reference and in WINDOWS.H with identifiers that begin with the word META. The low byte of this word identifies the particular GDI call; the high byte is generally the number of words that are parameters to the call. The words that follow this code are the actual parameters to the call in reverse order, excluding the hdc parameter. For instance, the GDI call:

Rectangle (hdcMeta, 0, 0, 100, 100) ;

shows up in the metafile as a seven-word record. In hexadecimal, these words are:

0007 0000 041B 0064 0064 0000 0000

The 041B word means that the call is Rectangle with four parameters, excluding the initial hdc. The parameters follow.

The only real exception to this rule is the SelectObject call. Windows must save the object that the function is selecting into the metafile device context. For instance, the call:

hBrush = CreateSolidBrush (RGB (0, 0, 255)) ;

doesn't affect the metafile device context at all. You can even make this call before you create the metafile device context with CreateMetaFile. When you select that brush into the metafile device context, however, two records must be generated. The first is a record for CreateBrushIndirect:

0007 0000 FC02 0000 0000 00FF 0000

The four words following the identifying code FC02 are the elements of the LOGBRUSH structure in the same order as the structure (lbStyle first).

The call:

SelectObject (hdcMeta, hBrush) ;

is coded in this record:

0004 0000 012D 0000

The single parameter 0000 indicates that it's a handle to the first object created in the metafile. Any following SelectObject calls with other GDI objects will have sequentially increasing parameters.

For a memory-based metafile, these records are stored in a global memory block. (You can obtain the records using the EnumMetaFile function.) For a disk-based metafile, the records are stored in a disk file. The handle to a disk-based metafile references a small global memory block that contains the drive, the directory, and the name of the file.