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.