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:
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());
CPoint ptOrg;
::GetViewportOrgEx(pDC->m_hDC,&ptOrg);
rectClip += ptOrg;
VERIFY(rgn.CreateRectRgnIndirect(rectClip));
}
else
{
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!
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.