Introduction
This article shows how to add print preview functionality to MFC CListView
class in report mode, preserving column order and relative column with. Note that this implementation does NOT try to fit all list columns on one page.
How it works
The OnBeginPrinting
function prepares printer fonts and calculates paper, page, header, footer and body rectangles.
void CListDemoViewPrint::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
m_pFontHeader = CreateFont(pDC,_T("Arial"), 12, FW_BOLD);
m_pFontFooter = CreateFont(pDC,_T("Arial"), 10);
m_pFontColumn = CreateFont(pDC,_T("Arial"), 9, FW_BOLD);
m_pFontBody = CreateFont(pDC,_T("Times New Roman"), 10);
m_CharSizeHeader = GetCharSize(pDC, m_pFontHeader);
m_CharSizeFooter = GetCharSize(pDC, m_pFontFooter);
m_CharSizeBody = GetCharSize(pDC, m_pFontBody);
m_rectPaper = GetPaperRect(pDC);
m_rectPage = GetPageRect();
m_rectHeader = GetHeaderRect();
...
m_RatioX = GetTextRatioX(pDC);
...
}
Character sizes are used later to calculate header and footer vertical height, body character size is used to calculate row (cell) height, number of rows per page and horizontal X ratio to adjust column width.
Character size is calculated simply by selecting font and getting sample string extent as follows.
CSize CListDemoViewPrint::GetCharSize(CDC* pDC, CFont* pFont)
{
CFont *pOldFont = pDC->SelectObject(pFont);
CSize charSize = pDC->GetTextExtent(_T("abcdefghijkl
mnopqrstuvwxyzABCDEFGHIJKLMNOPQRSATUVWXYZ"),52);
charSize.cx /= 52;
pDC->SelectObject(pOldFont);
return charSize;
}
Horizontal text ratio is calculated using body font character size and list control average character size.
double CListDemoViewPrint::GetTextRatioX(CDC* pDC)
{
ASSERT(pDC != NULL);
ASSERT(m_pListCtrl);
CDC* pCurrentDC = m_pListCtrl->GetDC();
TEXTMETRIC tmSrc;
pCurrentDC->GetTextMetrics(&tmSrc);
m_pListCtrl->ReleaseDC(pCurrentDC);
return ((double)m_CharSizeBody.cx) / ((double)tmSrc.tmAveCharWidth);
}
Using the code
Add the CListDemoViewPrint
class member to your CListView
derived class.
class CListDemoView : public CListView
{
...
CListDemoViewPrint m_Print;
};
Add the following printing functions to your class.
BOOL CListDemoView::OnPreparePrinting(CPrintInfo* pInfo)
{
m_Print.OnPreparePrinting(pInfo);
return DoPreparePrinting(pInfo);
}
void CListDemoView::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
m_Print.OnBeginPrinting(pDC, pInfo);
}
void CListDemoView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
m_Print.OnPrint(pDC, pInfo);
}
void CListDemoView::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)
{
m_Print.OnEndPrinting(pDC, pInfo);
}