Using Metafiles as Resources

In Chapter 8 you encountered a ”user-defined resource,“ which in that case was a block of text. Now let's transform a metafile into a user-defined resource. MYLOGO.WMF will then become part of the .EXE file for the program that needs it. The program MFRESORC (”metafile resource“), shown in Figure 13-5, accomplishes this using the MYLOGO.WMF metafile created by MFCREATE.

MFRESORC.MAK

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

# MFRESORC.MAK make file

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

mfresorc.exe : mfresorc.obj mfresorc.def mfresorc.res

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

rc mfresorc.res

mfresorc.obj : mfresorc.c

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

mfresorc.res : mfresorc.rc mylogo.wmf

rc -r mfresorc.rc

MFRESORC.C

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

MFRESORC.C -- Metafile Resource Program

(c) Charles Petzold, 1990

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

#include <windows.h>

long FAR PASCAL WndProc (HWND, WORD, WORD, LONG) ;

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,

LPSTR lpszCmdLine, int nCmdShow)

{

static char szAppName [] = "MFResorc" ;

HWND hwnd ;

MSG msg ;

WNDCLASS wndclass ;

if (!hPrevInstance)

{

wndclass.style = CS_HREDRAW | CS_VREDRAW ;

wndclass.lpfnWndProc = WndProc ;

wndclass.cbClsExtra = 0 ;

wndclass.cbWndExtra = 0 ; wndclass.hInstance = hInstance ;

wndclass.hIcon = NULL ;

wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;

wndclass.hbrBackground = GetStockObject (WHITE_BRUSH) ;

wndclass.lpszMenuName = NULL ;

wndclass.lpszClassName = szAppName ;

RegisterClass (&wndclass) ;

}

hwnd = CreateWindow (szAppName, "Metafile Resource Program",

WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, CW_USEDEFAULT,

CW_USEDEFAULT, CW_USEDEFAULT,

NULL, NULL, hInstance, NULL) ;

ShowWindow (hwnd, nCmdShow) ;

UpdateWindow (hwnd) ;

while (GetMessage (&msg, NULL, 0, 0))

{

TranslateMessage (&msg) ;

DispatchMessage (&msg) ;

}

return msg.wParam ;

}

long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)

{

static HANDLE hmf ;

static short cxClient, cyClient ;

HANDLE hInstance, hResource ;

HDC hdc ;

PAINTSTRUCT ps ;

short x, y ;

switch (message)

{

case WM_CREATE :

hInstance = ((LPCREATESTRUCT) lParam) -> hInstance ;

hResource = LoadResource (hInstance,

FindResource (hInstance, "MyLogo", "METAFILE")) ;

LockResource (hResource) ;

hmf = SetMetaFileBits (hResource) ;

UnlockResource (hResource) ;

return 0 ;

case WM_SIZE :

cxClient = LOWORD (lParam) ;

cyClient = HIWORD (lParam) ;

return 0 ;

case WM_PAINT :

hdc = BeginPaint (hwnd, &ps) ;

SetMapMode (hdc, MM_ANISOTROPIC) ;

SetWindowExt (hdc, 1000, 1000) ;

SetViewportExt (hdc, cxClient, cyClient) ;

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

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

{

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

PlayMetaFile (hdc, hmf) ;

}

EndPaint (hwnd, &ps) ;

return 0 ;

case WM_DESTROY :

DeleteMetaFile (hmf) ;

PostQuitMessage (0) ;

return 0 ;

}

return DefWindowProc (hwnd, message, wParam, lParam) ;

}

MFRESORC.RC

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

MFRESORC.RC resource script

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

MyLogo METAFILE "mylogo.wmf"

The resource script is only one line. METAFILE may look like a normal resource script keyword such as MENU or DIALOG, but it isn't. We're defining this resource type. The name we give to this particular resource of the METAFILE type is ”MyLogo.“

MFRESORC.DEF

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

; MFRESORC.DEF module definition file

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

NAME MFRESORC

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

EXETYPE WINDOWS

STUB 'WINSTUB.EXE'

CODE PRELOAD MOVEABLE DISCARDABLE

DATA PRELOAD MOVEABLE MULTIPLE

HEAPSIZE 1024

STACKSIZE 8192

EXPORTS WndProc

During processing of the WM_CREATE message, MFRESORC must first call FindResource and LoadResource to obtain a handle to the resource:

hResource = LoadResource (hInstance,

FindResource (hInstance, "MyLogo", "METAFILE")) ;

Then the resource is locked:

LockResource (hResource) ;

Normally, you would lock a resource to obtain a pointer to the memory block. However, LockResource also performs the chore of actually loading the resource into memory. That's all we need to do. Now we can convert this global memory block to a metafile using SetMetaFileBits, and the resource can be unlocked:

hmf = SetMetaFileBits (hResource) ;

GlobalUnlock (hResource) ;

SetMetaFileBits has a companion function, GetMetaFileBits, that converts a metafile handle to a global memory handle. GetMetaFileBits can be used only with a memory metafile.

The metafile that we loaded as a resource is a memory metafile. If you'd prefer to use a disk-based metafile, you can copy it. This is the code you would use following the GlobalUnlock statement:

GetTempFileName (0, MF, 0, szFileName) ;

hmf2 = CopyMetaFile (hmf, szFileName) ;

DeleteMetaFile (hmf) ;

hmf = hmf2 ;

The hmf2 handle need not be defined as a static variable. The MFRESORC program shows the deletion of the metafile handle during processing of WM_DESTROY:

DeleteMetaFile (hmf) ;

You should also delete the temporary file:

unlink (szFileName) ;

The CopyMetaFile function can also be used to copy an existing metafile to a memory metafile:

hmf2 = CopyMetaFile (hmf, NULL) ;