Metafile Dos and Don'ts

When you play the metafile, Windows breaks down the metafile into records and executes the appropriate functions using the parameters in each record. From the format of the metafile records, some facts should be fairly obvious (and some not so obvious).

The metafile device context is not a true device context. It doesn't correspond to an actual device or even to a block of memory like the memory device context. It's simply a repository for GDI calls you make using the hdcMeta device context handle.

The metafile device context doesn't have any default device context attributes. It uses whatever device context attributes are in effect when you play the metafile.

All parameters enter the metafile device context as numbers. For instance, if the width and height of your client area are stored in xClient and yClient, and you call:

Rectangle (hdcMeta, 0, 0, xClient / 2, yClient / 2) ;

then the actual calculated values of xClient / 2 and yClient / 2 will enter the metafile. If you later play back that metafile, it will draw a rectangle based on these calculated values regardless of the current size of the client area.

If you change the mapping mode of your screen device context before you play the metafile, the coordinates in the metafile will be interpreted based on the newly chosen mapping mode (unless the metafile itself changes the mapping mode).

The only calls that go into the metafile are those that take a handle to a device context as the first parameter. Many GDI calls are not allowed in a metafile. It's easier to say what functions cannot be used with a metafile device context, because they fall into several categories:

Any function that begins with the word Get, including GetDeviceCaps and GetTextMetrics. The metafile can do nothing with the information that these functions return.

Any other function designed to return information to the program: RectVisible, PtVisible, EnumFonts, EnumObjects, DPtoLP, and LPtoDP. The Escape function (which you'll encounter in Chapter 16) is supported only for calls that don't return data.

Any function that treats the metafile device context as if it were an actual device context: ReleaseDC, DeleteDC, CreateCompatibleDC, CreateCompatibleBitmap, CreateDiscardableBitmap, and PlayMetaFile.

Some of the more complex GDI functions: GrayString, DrawIcon, and SetBrushOrg.

Two functions that require handles to brushes: FillRect and FrameRect.

As I indicated above, SelectObject works a little differently for metafile device contexts. First, it doesn't return the handle of the object previously selected in the device context. When you use SelectObject with a metafile device context, the function returns a nonzero if it is successful and 0 otherwise. You can't use the construction:

DeleteObject (SelectObject (hdcMeta, . . . )) ; // WRONG !!!

For SelectObject, the metafile also stores a description of the logical object that you are selecting into the device context. When you play the metafile, Windows starts with the pen, brush, font, and region currently selected in the device context. For SelectObject calls, it creates the indicated object and selects it into the device context but saves the original object. When it is done playing the metafile, Windows restores the original objects and deletes all the objects it created to play the metafile.

When you play a metafile, it uses the device context attributes currently in effect. The metafile can change any of these attributes, including the mapping mode, the text color, the drawing mode, and so forth. These changes remain in effect for the device context af- ter the metafile has finished playing. If you want to retain your original device context attributes after the metafile has finished playing, call:

SaveDC (hdc) ;

before you play the metafile and:

RestoreDC (hdc, -1) ;

after the PlayMetaFile call. The metafile itself can also save and restore the device context while it is playing. Each SaveDC call must be balanced by a RestoreDC call with a -1 parameter.

One of the purposes of metafiles is to provide a format for device-independent pictures that can be shared by applications. There are some other considerations involved with using metafiles with the clipboard that will be discussed in Chapter 16.