Click here to Skip to main content
15,884,537 members
Articles / Programming Languages / C++
Article

Solution to the preview problem while playing a metafile in a CPreviewDC

Rate me:
Please Sign up or sign in to vote.
2.14/5 (4 votes)
26 Jan 2005CPOL1 min read 32.7K   12   1
Playing a Metfile into a CPreviewDC in print preview can cause further drawing operations to not work correctly.

Metafile played direct into preview DC

Metafile played into a bitmap and then rendered using StretchDIBits()

Introduction

I was checking into a print preview problem in one of our applications, where if we tried to render any clipboard output to the print preview screen, further drawing operations (but not all) on the same page would not work correctly. Typically, this would be seen as font text drawn at an incorrect angle or for clip regions in use not to work correctly, so that the was not be clipped.

I present in the demo code a way around this problem.

You can try running the demo application which demonstrates the problem. Its OnPrint() function looks like this:

void CPreviewMetafileView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
    CString text;
    CSize size;
    if (!IsClipboardFormatAvailable(CF_METAFILEPICT))
    {
        CString text("No METAFILE on clipboard");
        pDC->TextOut(0, 0, text);
    }

    CButton *pButton = static_cast<CButton*>(GetDlgItem(IDC_PREVIEW_DIRECT));
    bool previewDirect = (pButton->GetCheck() != 0);

    // rectangle to render the metafil into
    CRect metafileRect(pInfo->m_rectDraw.Width() / 2, 
        pInfo->m_rectDraw.top, 
        pInfo->m_rectDraw.right, 
        pInfo->m_rectDraw.Height() / 2);

    if (IsClipboardFormatAvailable(CF_METAFILEPICT))
    {
        if (previewDirect)
        {
            pDC->SaveDC();
            // play a metafile from the clipboard if available
            GLOBALHANDLE    hGMem;
            LPMETAFILEPICT  lpMFP;
            OpenClipboard();
            hGMem = GetClipboardData(CF_METAFILEPICT);
            lpMFP = (LPMETAFILEPICT)GlobalLock(hGMem);
            pDC->SaveDC();
            pDC->SetMapMode(lpMFP->mm);
            pDC->SetViewportExt(metafileRect.Width(), metafileRect.Height());
            pDC->SetViewportOrg(metafileRect.left, metafileRect.top);
            pDC->PlayMetaFile(lpMFP->hMF);
            VERIFY(pDC->RestoreDC(-1));
            GlobalUnlock(hGMem);
            CloseClipboard();
            pDC->RestoreDC(-1);
        }
        else
        {
            // render to offscreen bitmap and StretchDIBBits it
            DrawMetafileToDc(pDC, metafileRect);
        }
    }
    // the following output gets corrupted after a direct render
    text = "Text to be corrupted!";
    size = pDC->GetTextExtent(text);
    pDC->TextOut(0, size.cy, text);
    pDC->TextOut(0, size.cy * 2, text);
    pDC->TextOut(0, size.cy * 3, text);
}

As you can see, it checks to see if a metafile is available on the clipboard and renders it to the preview DC using either a direct render or an indirect render. It then adds some extra text to the output "Text to be corrupted". This text is not shown on the direct render but is on the indirect render. Although the way this corruption affects the output may be different depending on what you actually render after the metafile.

To get a metafile on the clipboard, a quick way is to copy some cells to the clipboard from Microsoft Excel.

The two functions you will be interested in the demo which you wish to use this work around are:

HANDLE CPreviewMetafileView::DDBToDIB(CBitmap& bitmap, 
                              DWORD dwCompression, CPalette* pPal)
void CPreviewMetafileView::DrawMetafileToDc(CDC * pDC, CRect targetRect)

Thats it!

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Sirius Analytical Instruments
United Kingdom United Kingdom
A research and development programmer working for a pharmaceutical instrument company for the past 17 years.

I am one of those lucky people who enjoys his work and spends more time than he should either doing work or reseaching new stuff. I can also be found on playing DDO on the Cannith server (Send a tell to "Maetrim" who is my current main)

I am also a keep fit fanatic, doing cross country running and am seriously into [url]http://www.ryushinkan.co.uk/[/url] Karate at this time of my life, training from 4-6 times a week and recently achieved my 1st Dan after 6 years.

Comments and Discussions

 
QuestionThe Demonstration Code Gone? Pin
wonea5-Oct-09 2:43
wonea5-Oct-09 2:43 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.