65.9K
CodeProject is changing. Read more.
Home

Using CRgn with print preview

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (12 votes)

Nov 4, 2003

CPOL

2 min read

viewsIcon

69657

CRgn objects need translating, to work correctly in print preview.

Some background

I was updating one of my classes today which prints a 2D graph, and to try and speed it up, we moved from a self clipping algorithm using y = mx + c and the graph boundaries to using a CRgn object to do the work for us. This made our code much simpler and hopefully quicker (we have yet to benchmark it).

We then moved on to some regression testing and found everything worked OK except that we got no output from the graph in print preview, although the graph would print correctly on the printer.

The problem

After checking through the code to make sure we had not done something stupid (the changes happened at the same time as upgrading the code that put data into the graph), we pin pointed the problem to the clip region we were using. Everything looked fine for the coordinates we were passing through to the creation of the CRgn object.

The problem was caused by the way the CPreviewDC class works. During preview mode you have 2 HDC objects active, the m_hAttribDC which is the HDC of the printer device context and the m_hDC which is the output DC. Now we were using a clip region that was correct for the printer device context, but not the output device context. When actually printing the attribute and output DCs are the same so we get correct output, but in preview mode, they are different. To get the output to work correctly, we needed to translate the clip region in use from the printer context to the output context.

A quick search of the MSDN turned up a problem report, PRB: Clipping Doesn't Work Correctly in Print Preview, but only because I knew what I was looking for. So that's why I am posting this fix myself here.

We were able to take the code posted there and translate the clip region units like this:

    // Now if we are in print preview mode then the clipping
    // rectangle needs to be adjusted before creating the
    // clipping region
    CRgn rgn;
    if (pDC->IsKindOf(RUNTIME_CLASS(CPreviewDC)))
    {
        CRect rectClip(m_axes);
        CPreviewDC *pPrevDC = static_cast<CPreviewDC*>(pDC);
        
        pPrevDC->PrinterDPtoScreenDP(&rectClip.TopLeft());
        pPrevDC->PrinterDPtoScreenDP(&rectClip.BottomRight());
        // Now offset the result by the viewport origin of
        // the print preview window...

        CPoint ptOrg;
        ::GetViewportOrgEx(pDC->m_hDC,&ptOrg);
        rectClip += ptOrg;
        VERIFY(rgn.CreateRectRgnIndirect(rectClip));
    }
    else
    {
        // just use the regular clip area as we are not in preview mode
        VERIFY(rgn.CreateRectRgnIndirect(m_axes));
    }
    pDC->SelectClipRgn(&rgn);
    VERIFY(rgn.DeleteObject());

    ...
    pDC->SelectClipRgn(NULL);

So this sorted the problem for us. I hope this reference here helps you out.

Enjoy!