Microsoft KB Archive/105443

= PRB: MetaFile Displays Incorrectly in Print Preview =

Article ID: 105443

Article Last Modified on 11/21/2006

-

APPLIES TO

 Microsoft Foundation Class Library 4.2, when used with:  Microsoft Visual C++ 1.0 Professional Edition

 Microsoft Visual C++ 1.5 Professional Edition

 Microsoft Visual C++ 1.51

 Microsoft Visual C++ 1.52 Professional Edition</li></ul>

 Microsoft Visual C++ 1.0 Professional Edition</li></ul>

 Microsoft Visual C++ 2.0 Professional Edition</li></ul>

 Microsoft Visual C++ 2.1</li></ul>

 Microsoft Visual C++ 2.2</li></ul>

 Microsoft Visual C++ 4.0 Standard Edition</li></ul> </li></ul>

-

<div class="notice_section">

This article was previously published under Q105443

<div class="symptoms_section">

SYMPTOMS
When displaying a metafile within the Microsoft Foundation Classes (MFC) Print and Print Preview architecture, the metafile prints correctly but is only partially or incorrectly displayed in the Print Preview window.

<div class="cause_section">

CAUSE
To simulate a printed page in a window, CPreviewDC modifies the mapping mode for the Print Preview window by changing the parameters for such calls as SetWindowExt and SetMapMode before passing them on to the attribute and output device contexts (DCs).

However, CPreviewDC does not override CDC::PlayMetaFile, which maps to the Windows application programming interface (API) ::PlayMetaFile. If the metafile contains records for functions that affect the mapping mode, the CPreviewDC versions of these functions will not be called while the metafile is playing, causing the mapping mode in the Print Preview window to be set incorrectly (the attribute and output DCs lose synchronization).

<div class="resolution_section">

RESOLUTION
Rather than PlayMetaFile, use SaveDC, ::EnumMetaFile, and RestoreDC to play the metafile. In the metafile enumeration callback procedure, trap the following functions and call the equivalent CDC functions: <pre class="fixed_text">  SetMapMode SetWindowExt, ScaleWindowExt SetViewportExt, ScaleViewportExt SetViewportOrg, OffsetViewportOrg (Of these, SetWindowExt occurs in metafiles more often than the rest. It is generally not recommended that metafiles contain records for SetMapMode or any of the Viewport functions, but it is common to find SetMapMode records in metafiles anyway.)

Bracket the call to ::EnumMetaFile between calls to SaveDC and RestoreDC to ensure that the output and attribute DCs are correctly synchronized after playing the metafile.

<div class="moreinformation_section">

MORE INFORMATION
The enumeration callback procedure should handle the above functions by calling the (virtual) CDC version of the function while passing everything else to PlayMetaFileRecord. This allows CPreviewDC to keep the output DC and the attribute DC correctly synchronized with respect to mapping mode. For example:

Sample Code
int CALLBACK __export EnumMFProc(HDC hdc,                                   HANDLETABLE FAR *lpht,                                    METARECORD  FAR *lpmr,                                    int cObj,                                    LPARAM lParam) {    // lParam is available for passing application-specific data to the // enum proc (via the last parameter to EnumMetaFile). Let's make // things easier by passing in a pointer to the CDC object. CDC *pDC = (CDC *)lParam; switch(lpmr->rdFunction) {      // SetWindowExt and SetMapMode are the most important ones to       // look for. case META_SETWINDOWEXT: pDC->SetWindowExt(lpmr->rdParm[1], lpmr->rdParm[0]); break; case META_SETMAPMODE: pDC->SetMapMode(lpmr->rdParm[0]); break; case META_SETVIEWPORTEXT: pDC->SetViewportExt(lpmr->rdParm[1], lpmr->rdParm[0]); break; case META_SETVIEWPORTORG: pDC->SetViewportOrg(lpmr->rdParm[1], lpmr->rdParm[0]); break; // Add cases for the others if desired... default: PlayMetaFileRecord(hdc, lpht, lpmr, cObj); }    return 1; } In addition to the functions listed above, there are other functions that will not affect the appearance of the metafile in the Print Preview window, but may affect the synchronization of the output and attribute DCs used by CPreviewDC. This can affect subsequent drawing. Consider that the metafile may select different fonts and other objects into the output DC, may change the foreground/background colors, the text alignment flags, and so forth.

Also, it is common for applications to set a different mapping mode before playing a metafile (depending on the metafile) and this mapping mode may conflict with the mapping mode used by the rest of the view class.

For these reasons, if any drawing will take place after playing the metafile (including playing another metafile, or even the same metafile again), the DC must be restored to the state it was in prior to playing the metafile. This can be accomplished by using SaveDC/RestoreDC, as in the following example: pDC->SaveDC;                    // Save current state of DC   pDC->SetMapMode(MM_ANISOTROPIC);   // Scalable metafile pDC->SetViewportExt(xExt, yExt);  // Size of picture pDC->SetViewportOrg(x, y);        // Location of picture



pDC->RestoreDC(-1);               // Restore to previous saved state // Continue with other drawing...

Keywords: kbmetafile kbprint kbprb KB105443

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.