Print ListCtrl on multiple pages






4.96/5 (14 votes)
Printing the contents of a CListCtrl or CListView with multiple pages
The demo consists of a doc/view-framework with a CListView
-class. It has a button to fill with data and another to print the stuff.
The Problem
MFC has no built-in feature for printing a List Control. Some approaches can be found on the internet but they always have the problem that if you have more columns then will fit to a single page, then the rest is clipped away and not printed.
The Solution
My class manages:
- Printing a CListCtrl or CListView with support for multiple pages
- The first column is printed again on each page
- The width of the columns are used for printing
- Columns can be sorted (nothing new, I know)
My appraoch is mainly based on the fabulous work of Dan Pilat with his article Printing with MFC Made Easy.
My work was to build a kind of wrapper over his classes and do the newpage-logic. Each single page is printed just by his classes with some overriden virtual functions.
The printing from the CListView
then looks like this:
void CListPrintView::OnFilePrintDirect()
{
CWaitCursor wait;
CListCtrl &listctrl = GetListCtrl();
CListCtrlPrintJob job(&listctrl, !m_bUseSetup);
job.Print();
}
The trick is to calculate a translater for Screen [Pixels] -> Printer [mm]. Then I know how much space a column needs on the paper. This helps me calculating the amount of columns that fit to a page.
I then loop through all columns and count their width.
When its time to begin a new one, I define a print-job the Dan Pilat way.
void CListCtrlPrintJob::OnPrint() { ... widthOfPage = m_pListCtrl->GetColumnWidth(0); iStart = 1; for( i=1 ; i<m_ColCount ; i++ ) { widthThisCol = m_pListCtrl->GetColumnWidth(i); bNewPage = FALSE; if( widthOfPage+widthThisCol > paperWidthInPixel ) { // not enough place on side, begin new one bNewPage = TRUE; } else { // also print the last one if( i == (m_ColCount-1) ) bNewPage = TRUE; // this col needs this space: widthOfPage += widthThisCol; } if( bNewPage ) { // ok, print it on a new page CListCtrlDataPage data(this, m_pListCtrl, iStart, i); data.Print(); iStart = i+1; widthOfPage = m_pListCtrl->GetColumnWidth(0); } } }
CListCtrlDataPage
is derived from GPrintUnit
and also has this print-function:
BOOL CListCtrlDataPage::Print() { ... zeilenMax = m_pListCtrl->GetItemCount(); for( zeile=0 ; zeile<zeilenMax ; zeile++ ) { nRC = StartRow(); // first Col if( m_pListCtrl->GetItemText(zeile, 0, szText, sizeof(szText)) ) PrintCol(colId, szText, DT_LEFT); colId++; for( spalte=m_firstCol ; spalte<=m_lastCol ; spalte++ ) { if( m_pListCtrl->GetItemText(zeile, spalte, szText, sizeof(szText)) ) PrintCol(colId, szText, DT_LEFT); colId++; } EndRow(); } EndPage(); ... }
Do you have Enchancements (e.g. a print-preview) ?
Let me know: Markus Loibl, Germany