Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WTL Metafile Helper

0.00/5 (No votes)
12 Oct 2002 1  
This article describes a helper class that can load metafiles from either resource or disk. It supports both windows and enhanced metafiles.
Figure 1. Metafile in static control

Figure 2. Metafile as background image

Introduction

This article explains how to use the CMeta class in a WTL application. The sample project included with this article is a wizard-generated dialog application enhanced with two static controls to display metafile images. The About dialog demonstrates using a metafile as a background image. The class supports both windows and enhanced metafiles and can load either resources or disk files.

Metafiles

There are two types of metafile images: the older Windows Metafile (WMF) and the newer Enhanced Metafile (EMF). WMF files are readily available as part of clipart collections and are installed with several Microsoft products. EMF is less popular but used internally in several software functions, such as print previewers. Both types are scalable and support image transparency.

Using CMeta

CMeta inherits from CEnhMetaFile which is in the WTL atlgdi.h header file. It adds support for loading both windows and enhanced metafiles from either resource or disk file. For ease of use, windows metafiles are converted to enhanced, upon load. After a metafile is loaded, it can be assigned to a static or other control that supports enhanced metafiles. These are the basic steps to display a metafile resource in a static control on a dialog:

  1. Include Meta.h in the application .cpp
  2. Use the resource editor to import a Metafile (custom resource) to the project
  3. Add a CMeta member variable to the dialog class
  4. Load the metafile from resource in OnInitDialog()
  5. Use the resource editor to add a static control to the dialog
  6. Set the static control type to Enhanced Metafile
  7. Use SetEnhMetaFile() to assign the metafile to the static control

Here is example code from OnInitDialog() showing how to load the metafile image from resource:

// FALSE = WMF, TRUE = EMF

m_meta.LoadMetaResource(IDR_BIRD, FALSE);
CStatic(GetDlgItem(IDC_STATIC1)).SetEnhMetaFile(m_meta);

A metafile can also be "played" onto a device context using PlayEnhMetaFile() after it is loaded from resource or disk. These are the basic steps to play a metafile resource on a dialog's device context:

  1. Step 1 through 4 from above
  2. Use PlayEnhMetaFile() to (dis)play the metafile

The section "Background Image" later in this article explains how to set up message handlers and play the metafile as a dialog background image. In the sample project, this is demonstrated in the About dialog.

LoadMetaResource()

The LoadMetaResource() method is used to load either an enhanced or windows metafile resource. A resource is binary data that a resource compiler adds to an application's executable file. There are standard resources, such as icons and strings, and custom resources, which can be virtually anything. Both types of metafiles are custom resources. Call the Custom Resource Type either Metafile or EnhMetafile as appropriate when importing a metafile.

LoadMetaResource() accepts a resource ID as input and sets the m_hEMF variable to the handle of the resultant metafile. A boolean input parameter indicates whether the metafile is enhanced (TRUE) or windows (FALSE).

LoadMetaFile()

LoadMetaFilee() accepts a boolean input parameter to indicate whether the metafile is enhanced (TRUE) or windows (FALSE). It also accepts an optional file name and prompts the user with a standard file open dialog if no file name parameter is supplied.

When you click the File button on the sample project's main dialog, it calls the following method to load a disk-based metafile. m_left is the CMeta member variable for the metafile used in the left static control.

LRESULT OnFileOpen(WORD, WORD, HWND, BOOL&)
{ // load a windows metafile. Prompt user for file name

  m_left.LoadMetaFile(m_hWnd, FALSE);

  // load and refresh the static control

  CStatic st(GetDlgItem(IDC_STATIC1));
  st.SetEnhMetaFile(m_left);
  st.Invalidate();

  return 0; }

Background Image

An example of how to use a metafile as a background image is provided in the About dialog of the sample project. The basic steps for how to "play" a metafile were discussed earlier in the article. In addition to those steps, a WM_ERASEBKGND message is added to the dialog's message map and the following handler is added to process the message. m_bkgnd is the CMeta member variable and wParam carries the dialog's device context.

LRESULT OnEraseBkgnd(UINT, WPARAM wParam, LPARAM, BOOL&)
{
  RECT rc;
  GetClientRect(&rc);

  // fill in background color

  ::FillRect((HDC)wParam, &rc, (HBRUSH)(COLOR_BACKGROUND));

  // paint background metafile

  return ::PlayEnhMetaFile((HDC)wParam, m_bkgnd, &rc);
}

In addition, add WM_CTLCOLORSTATIC to the message map and use this message handler so that static controls transparently display over the background image:

LRESULT OnCtlColorStatic(UINT, WPARAM wParam, LPARAM lParam, BOOL&)
{
  SetBkMode((HDC)wParam, TRANSPARENT);

  // return a null brush so image behind static isn't erased

  return (LRESULT)::GetStockObject(NULL_BRUSH);
}

Terms Of Use

The sample application and source code available with this article, is free for any purpose.

THIS SOFTWARE IS DISTRIBUTED AS-IS, WITHOUT WARRANTIES OF ANY KIND.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here