HOWTO: Draw on a Pre-Existing Enhanced Metafile

ID: Q230675


The information in this article applies to:


SUMMARY

Sometimes it is desirable to draw on the surface of a pre-existing enhanced metafile. Unfortunately, the GetEnhMetaFile() API returns an HENHMETAFILE handle rather than a device context. This article shows how to create a device context that contains the contents of a disk-based EMF, and on which you can draw using normal GDI APIs.


MORE INFORMATION

The following steps show how to create a device context (DC) from a pre-existing EMF:

  1. Load the source EMF using GetEnhMetaFile().


  2. Calculate the size of the source EMF from its header.


  3. Create a new EMF DC that is the same size as the original.


  4. Play the source EMF on to the new DC.


The following code demonstrates this approach:

// This function returns an EMF HDC, on which has already been drawn the contents of the source EMF.
HDC MakeNewWritableMetafile( LPTSTR szSourceFileName, LPTSTR szTargetFileName )
{
	HENHMETAFILE	hSourceEMF;
	HDC				hTargetDC, hRefDC;
	ENHMETAHEADER	emh;
	RECT			Rect, rcSource;
	float			PixelsX, PixelsY, MMX, MMY;

	// Get a reference DC. Normally, you'd get the highest resolution DC available,
	//    for example a printer DC. We just use a screen DC for this demonstration.
	if( (hRefDC = GetDC( NULL )) == NULL )
		return NULL;
	// Open the source EMF
	if( (hSourceEMF = GetEnhMetaFile( szSourceFileName )) == NULL )
	{
		ReleaseDC( NULL, hRefDC );
		return NULL;
	}

	// Get the header from the enhanced metafile.
	ZeroMemory( &emh, sizeof(ENHMETAHEADER) );
	emh.nSize = sizeof(ENHMETAHEADER);
	if( GetEnhMetaFileHeader( hSourceEMF, sizeof( ENHMETAHEADER ), &emh ) == 0 )
	{
		DeleteEnhMetaFile( hSourceEMF );
		ReleaseDC( NULL, hRefDC );
		return NULL;
	}

	// Get the characteristics of the output device.
	PixelsX = (float)GetDeviceCaps( hRefDC, HORZRES );
	PixelsY = (float)GetDeviceCaps( hRefDC, VERTRES );
	MMX = (float)GetDeviceCaps( hRefDC, HORZSIZE );
	MMY = (float)GetDeviceCaps( hRefDC, VERTSIZE );

	// Calculate the rect in which to draw the metafile based on the
	// intended size and the current output device resolution.
	// Remember that the intended size is given in 0.01 mm units, so
	// convert those to device units on the target device.
	Rect.top = (int)((float)(emh.rclFrame.top) * PixelsY / (MMY*100.0f));
	Rect.left = (int)((float)(emh.rclFrame.left) * PixelsX / (MMX*100.0f));
	Rect.right = (int)((float)(emh.rclFrame.right) * PixelsX / (MMX*100.0f));
	Rect.bottom = (int)((float)(emh.rclFrame.bottom) * PixelsY / (MMY*100.0f));

	// Create the new metafile the same size as the old one.
	SetRect( &rcSource, emh.rclFrame.left, emh.rclFrame.top, emh.rclFrame.right, emh.rclFrame.bottom );
	hTargetDC = CreateEnhMetaFile( hRefDC, szTargetFileName, &rcSource, "Desc\0Desc\0\0" );
	// Play the old metafile on to the new one.
	PlayEnhMetaFile( hTargetDC, hSourceEMF, &Rect );
	// Clean up.
	DeleteEnhMetaFile( hSourceEMF );
	ReleaseDC( NULL, hRefDC );
	return hTargetDC;
} 


REFERENCES

For additional information about how to read all kinds of metafiles, please see the following article in the Microsoft Knowledge Base:

Q145999 SAMPLE: How to Create & Play Enhanced Metafiles in Win32

Additional query words: enhanced metafile emf wmf


Keywords          : kbGDI kbMetafile kbSDKWin32 kbGrpGDI 
Version           : WINDOWS:95,98,98 Second Edition; winnt:
Platform          : WINDOWS winnt 
Issue type        : kbhowto 

Last Reviewed: May 7, 1999