Using Preexisting Metafiles

What we've done in the last example above seems to imply that we can create a disk-based metafile in one program and then use it in another program by calling GetMetaFile. We can. The MFCREATE (”metafile create“) program, shown in Figure 13-4, is the shortest Windows program in this book. All it does is create a disk-based metafile with the name MYLOGO.WMF. The .WMF extension stands for ”Windows metafile“ and is the customary extension for a metafile stored as a disk file.

MFCREATE.MAK

#------------------------

# MFCREATE.MAK make file

#------------------------

mfcreate.exe : mfcreate.obj mfcreate.def

link mfcreate, /align:16, NUL, /nod slibcew libw, mfcreate

rc mfcreate.exe

mfcreate.obj : mfcreate.c

cl -c -Gsw -Ow -W2 -Zp mfcreate.c

MFCREATE.C

/*-----------------------------------------

MFCREATE.C -- Metafile Creation Program

(c) Charles Petzold, 1990

-----------------------------------------*/

#include <windows.h>

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,

LPSTR lpszCmdLine, int nCmdShow)

{

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

HDC hdcMeta = CreateMetaFile ("MYLOGO.WMF") ;

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

MoveTo (hdcMeta, 0, 0) ;

LineTo (hdcMeta, 100, 100) ;

MoveTo (hdcMeta, 0, 100) ;

LineTo (hdcMeta, 100, 0) ;

SelectObject (hdcMeta, hBrush) ;

Ellipse (hdcMeta, 20, 20, 80, 80) ;

DeleteMetaFile (CloseMetaFile (hdcMeta)) ;

DeleteObject (hBrush) ;

MessageBeep (0) ;

return FALSE ;

}

MFCREATE.DEF

;-------------------------------------

; MFCREATE.DEF module definition file

;-------------------------------------

NAME MFCREATE

DESCRIPTION 'Metafile Creation Program (c) Charles Petzold, 1990'

EXETYPE WINDOWS

STUB 'WINSTUB.EXE'

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD MOVEABLE MULTIPLE

HEAPSIZE 1024

STACKSIZE 8192

In the WinMain function, MFCREATE creates a metafile device context using the filename MYLOGO.WMF:

hMetaDC = CreateMetaFile ("MYLOGO.WMF") ;

It then draws on this device context. When it's finished, it closes the metafile device context and deletes the metafile handle in one statement:

DeleteMetaFile (CloseMetaFile (hdcMeta)) ;

The program beeps to indicate that it's finished and then exits WinMain.

Now you can use this metafile in another program. Here's the entire WM_PAINT logic. All you need to obtain the handle to the disk-based metafile is GetMetaFile. When you're done with the metafile, you call DeleteMetaFile:

hdc = BeginPaint (hwnd, &ps) ;

SetMapMode (hdc, MM_ANISOTROPIC) ;

SetWindowExt (hdc, 1000, 1000) ;

SetViewportExt (hdc, xClient, yClient) ;

hmf = GetMetaFile ("MYLOGO.WMF") ;

for (x = 0 ; x < 10 ; x++)

for (y = 0 ; y < 10 ; y++)

{

SetWindowOrg (hdc, -100 * x, -100 * y) ;

PlayMetaFile (hdc, hmf) ;

}

DeleteMetaFile (hmf) ;

EndPaint (hwnd, &ps) ;

Alternatively, you can define hmf as a static variable and call GetMetaFile once during processing of WM_CREATE and call DeleteMetaFile during processing of WM_DESTROY. Of course, this approach has some problems. The code assumes that MYLOGO.WMF is in the current directory or a directory listed in the PATH environment variable. If the file isn't in the current directory when you call GetMetaFile, Windows will display a message box asking the user to insert the MYLOGO.WMF disk in drive A. (The usual response of a user to a message box of this sort is ”Huh?“) You should search for the file before you call GetMetaFile.

Now let's try another approach.