Storing Metafiles on Disk

In the above example, the NULL parameter to CreateMetaFile meant that we wanted to create a metafile stored in memory. We can also create a metafile stored on the disk as a normal file. This method is preferred for large metafiles because it uses less memory space. Windows has to maintain a relatively small area in memory to store the name of the file containing the metafile. On the other hand, a metafile stored on disk requires a disk access every time you play it.

Let's use the example of the company logo again. In addition to the variables shown above, you'll need a variable to store the filename of the metafile:

static char szFileName [80] ;

In this example, we'll use a temporary file. During processing of the WM_CREATE message, you can create a filename for a temporary file using the Windows GetTempFileName function:

GetTempFileName (0, MF, 0, szFileName) ;

Windows first checks the TEMP variable in the MS-DOS environment to select a disk and subdirectory for this file. If there is no TEMP variable in the MS-DOS environment, Windows uses the root directory of the first fixed disk. The filename begins with a tilde (~) followed by the characters we've specified in the GetTempFileName function (MF) and a unique number; the extension is .TMP. On return from the call, the filename is stored in the szFileName array.

We create the metafile device context using this filename:

hMetaDC = CreateMetaFile (szFileName) ;

We can write to this device context just as we did in the original example and then close the metafile device context to get the metafile handle:

hmf = CloseMetaFile (hdcMeta) ;

The processing of the WM_PAINT message is the same as in the original example. However, during processing of the WM_DESTROY message, you'll have to add something. The statement:

DeleteMetaFile (hmf) ;

deletes the area of memory that references the metafile handle to the disk file, but the disk file still exists. You should also delete that file using the normal C function:

unlink (szFileName) ;

Here's another way to use disk-based metafiles. This method doesn't require that you maintain hmf as a static variable. First, you get a temporary filename and create the metafile device context as before:

GetTempFileName (0, MF, 0, szFileName) ;

hdcMeta = CreateMetaFile (szFileName) ;

Now you draw on the metafile device context. When you're finished, you can close the device context and get a handle to the metafile:

hmf = CloseMetaFile (hdcMeta) ;

But now you also delete the metafile:

DeleteMetaFile (hmf) ;

Do we really want to do this? We might. Deleting a disk-based metafile invalidates the metafile handle, freeing the memory required for the metafile but leaving the disk file intact. During processing of the WM_PAINT message, you can get a metafile handle to this disk file by calling GetMetaFile:

hmf = GetMetaFile (szFileName) ;

Now you can play this metafile just as before. When processing of the WM_PAINT message is over, you can delete the metafile handle:

DeleteMetaFile (hmf) ;

When it comes time to process the WM_DESTROY message, you don't have to delete the metafile, because it was deleted at the end of the WM_CREATE message and at the end of each WM_PAINT message. But you still should delete the disk file:

unlink (szFileName) ;