VC++
Example: OnPreparePrinting
and
OnBeginPrinting and
OnEndPrinting, Plug-in
class to support printing
from a listview
|
|
Gregory Goeppel
February 2, 1999
read and used "Print
the contents of the list control" by Ravi Reddy, as a
basis for this code.
His code is very good. However, I wanted a class that I
could just plop into my view class as a contained member
object to take over printing the list control. My class is
LCPrinting.
Differences between
LCPrinting and Ravi Reddy's code:
LCPrinting does not print
in color (only black and white).
It does not print
icons. It only prints a list control in report
view.
It is a contained class.
Just add it as a member to your view class.
It has support for column
ordering (up to 30 columns.If U need more change it)
It guesses at the number
of pages B4 the print
dialog comes up.
It prints
lines after each row.
It prints the header
control manually instead of having the header print
itself. This gives more control in how the header appears
on a page.
Implementation:
Just add an LCPrinting
member object to your view class like this:
LCPrinting lcp;
Override the following printing
functions in your view class like so this:
BOOL CStocky5View::OnPreparePrinting(CPrintInfo* pInfo)
{
return lcp.OnPreparePrinting(pInfo, this, &lc);
}
void CStocky5View::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo)
{
CStocky5Doc* pDoc = GetDocument();
CMainFrame * mf_ptr = (CMainFrame *)AfxGetMainWnd();
CString doc_title = pDoc->GetTitle();
lcp.OnBeginPrinting(pDC, pInfo, doc_title, mf_ptr->fdc.date);
return;
}
void CStocky5View::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
lcp.OnPrint(pDC, pInfo);
return;
}
void CStocky5View::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)
{
lcp.OnEndPrinting(pDC, pInfo);
CListView::OnEndPrinting(pDC, pInfo);
return;
}
Here is
the class header file:
#ifndef G_LC_PRINTING
#define G_LC_PRINTING
class LCPrinting
{
public:
LCPrinting();
BOOL OnPreparePrinting(CPrintInfo* pInfo, CView * cview, CListCtrl * t_lc);
void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo, CString & t_title, CString & t_date);
void OnPrint(CDC* pDC, CPrintInfo* pInfo);
void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
protected:
CListCtrl * lc;
CString TitleStr;
CString DateStr;
CFont * pOldFont;
CFont BoldFont;
CFont lcFont;
CRect page_rc;
int m_nRowHeight;
int m_nRowsPerPage;
int m_nMaxRowCount;
int hc_items;
unsigned int m_ratiox;
unsigned int m_ratioy;
void PrintHeaderControl(CDC *pDC, CPrintInfo *pInfo);
void PrintHeader(CDC *pDC, CPrintInfo *pInfo);
void PrintFooter(CDC *pDC, CPrintInfo *pInfo);
void DrawRow(CDC *pDC, int nItem);
void draw_line_at(CDC *pDC, unsigned int y);
void compute_metrics(CDC *pDC);
};
#endif
Here is
the .cpp file:
#include "stdafx.h"
#include "LCPrinting.h"
#define LEFT_MARGIN 2
#define RIGHT_MARGIN 4
#define HEADER_HEIGHT 4
#define FOOTER_HEIGHT 3
LCPrinting::LCPrinting()
{
lc = 0;
pOldFont = 0;
TitleStr = "";
DateStr = "";
page_rc.SetRect(0,0,0,0);
m_nRowHeight = 0;
m_nRowsPerPage = 0;
m_nMaxRowCount = 0;
m_ratiox = 0;
m_ratioy = 0;
hc_items = 0;
return;
}
BOOL LCPrinting::OnPreparePrinting(CPrintInfo* pInfo, CView * cview, CListCtrl * t_lc)
{
if(t_lc==NULL || cview==NULL || pInfo == NULL) return FALSE;
lc = t_lc;
CPrintDialog pdlg(FALSE);
if (!pdlg.GetDefaults()) return FALSE;
CDC t_pDC;
t_pDC.Attach(pdlg.GetPrinterDC());
compute_metrics(&t_pDC);
m_nMaxRowCount = lc->GetItemCount(); if(!m_nMaxRowCount) return FALSE;
int nMaxPage = m_nMaxRowCount/m_nRowsPerPage + 1;
pInfo->SetMaxPage(nMaxPage);
pInfo->m_nCurPage = 1;
pInfo->m_pPD->m_pd.Flags |=PD_HIDEPRINTTOFILE;
return cview->DoPreparePrinting(pInfo);
}
OnBeingPrinting function
void LCPrinting::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo, CString & t_title, CString & t_date)
{
if(pDC == NULL || pInfo==NULL)
return;
TitleStr = t_title;
DateStr = t_date;
LOGFONT lf;
CFont * lcfont_ptr = lc->GetFont();
lcfont_ptr->GetLogFont(&lf);
lcFont.CreateFontIndirect(&lf);
lf.lfWeight = FW_BOLD;
lf.lfHeight+=22;
lf.lfWidth = 0;
BoldFont.CreateFontIndirect(&lf);
compute_metrics(pDC);
int nMaxPage = m_nMaxRowCount/m_nRowsPerPage + 1;
pInfo->SetMaxPage(nMaxPage);
pInfo->m_nCurPage = 1;
return;
}
void LCPrinting::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
if(NULL == pDC || NULL == pInfo)
return;
pOldFont = pDC->GetCurrentFont();
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(1, 1);
pDC->SetViewportExt(m_ratiox, m_ratioy);
int nStartRow = (pInfo->m_nCurPage - 1)*m_nRowsPerPage;
int nEndRow = nStartRow+m_nRowsPerPage;
if(nEndRow > m_nMaxRowCount)
nEndRow = m_nMaxRowCount;
PrintHeader(pDC, pInfo);
pDC->SetWindowOrg(-1*page_rc.left, 0);
PrintFooter(pDC, pInfo);
pDC->SetWindowOrg(-1*page_rc.left, -1*HEADER_HEIGHT*m_nRowHeight);
PrintHeaderControl(pDC, pInfo);
pDC->SelectObject(&lcFont);
pDC->SetTextColor(RGB(0,0,0));
pDC->SetBkColor(RGB(255,255,255));
CRect rcBounds;
lc->GetItemRect(nStartRow, &rcBounds, LVIR_BOUNDS);
CRect rc;
lc->GetHeaderCtrl()->GetClientRect(&rc);
rcBounds.OffsetRect(0, -rc.Height());
pDC->OffsetWindowOrg(rcBounds.left, rcBounds.top);
for(int i = nStartRow; i < nEndRow; i++)
DrawRow(pDC, i);
pDC->SetWindowOrg(0,0);
pDC->SelectObject(pOldFont);
return;
}
void LCPrinting::PrintHeader(CDC *pDC, CPrintInfo *pInfo)
{
pDC->SelectObject(&BoldFont);
pDC->SetTextColor(RGB(0,0,0));
pDC->SetBkColor(RGB(255,255,255));
CRect rc = page_rc;
rc.bottom = rc.top+m_nRowHeight;
pDC->DrawText(TitleStr, &rc, DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_RIGHT | DT_NOCLIP);
return;
}
print footer with a line and date, and page number
void LCPrinting::PrintFooter(CDC *pDC, CPrintInfo *pInfo)
{
CRect rc = page_rc;
rc.top = rc.bottom - FOOTER_HEIGHT*m_nRowHeight;
rc.bottom = rc.top + m_nRowHeight;
draw_line_at(pDC, rc.top);
CString sTemp ;
rc.OffsetRect(0, m_nRowHeight/2);
sTemp.Format("%d", pInfo->m_nCurPage);
pDC->DrawText(sTemp,-1,rc, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
pDC->DrawText(DateStr,-1,rc, DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
return;
}
void LCPrinting::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)
{
lcFont.DeleteObject();
BoldFont.DeleteObject();
return;
}
void LCPrinting::compute_metrics(CDC *pDC)
{
CRect row_rc; lc->GetItemRect(0, &row_rc, LVIR_BOUNDS);
CDC *pCtlDC = lc->GetDC(); if(NULL == pCtlDC) return;
TEXTMETRIC tm; pCtlDC->GetTextMetrics(&tm);
m_ratiox = pDC->GetDeviceCaps(HORZRES)/(row_rc.Width() + (LEFT_MARGIN+RIGHT_MARGIN)*tm.tmAveCharWidth);
m_ratioy = pDC->GetDeviceCaps(LOGPIXELSY)/pCtlDC->GetDeviceCaps(LOGPIXELSY);
lc->ReleaseDC(pCtlDC);
page_rc.SetRect(0,0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
page_rc.bottom = page_rc.bottom/m_ratioy;
page_rc.right = page_rc.right/m_ratiox;
page_rc.left = LEFT_MARGIN*tm.tmAveCharWidth;
page_rc.right -= RIGHT_MARGIN*tm.tmAveCharWidth;
m_nRowHeight = row_rc.Height();
int pRowHeight = (int)(m_nRowHeight*m_ratioy);
m_nRowsPerPage = pDC->GetDeviceCaps(VERTRES)/pRowHeight;
m_nRowsPerPage -= (HEADER_HEIGHT+FOOTER_HEIGHT);
m_nRowsPerPage -= 1;
return;
}
void LCPrinting::PrintHeaderControl(CDC *pDC, CPrintInfo *pInfo)
{
UINT dtFlags = DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER|DT_LEFT;
CHeaderCtrl* hc = lc->GetHeaderCtrl();
hc_items = hc->GetItemCount();
if (hc_items < 1) return;
int order_array[30];
hc->GetOrderArray(order_array, hc_items);
char temp_str[1024];
HDITEM phi;
phi.mucancode.net = HDI_TEXT | HDI_WIDTH ;
phi.cchTextMax = 1024;
phi.pszText = temp_str;
CRect rc(0,0,0,m_nRowHeight);
for (int i = 0; i < hc_items; i++)
{
hc->GetItem(order_array[i], &phi);
rc.right += phi.cxy;
pDC->DrawText(temp_str, -1, rc, dtFlags);
rc.left += phi.cxy;
}
draw_line_at(pDC, rc.bottom);
return;
}
void LCPrinting::DrawRow(CDC *pDC, int nItem)
{
if (hc_items < 1)
return;
int order_array[30];
lc->GetColumnOrderArray(order_array, hc_items);
CString temp_str;
LV_COLUMN lvc;
lvc.mucancode.net = LVCF_WIDTH;
CRect rc; lc->GetItemRect(nItem, rc, LVIR_LABEL);
int offset = pDC->GetTextExtent(" ", 1).cx;
rc.left += offset/2;
rc.right -= offset;
for (int i = 0; i < hc_items; i++)
{
lc->GetColumn(order_array[i], &lvc);
temp_str = lc->GetItemText(nItem, order_array[i]);
rc.right += lvc.cx;
pDC->DrawText(temp_str, -1, rc, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER|DT_LEFT);
draw_line_at(pDC, rc.bottom);
rc.left += lvc.cx;
}
return;
}
draw the line at.
void LCPrinting::draw_line_at(CDC *pDC, unsigned int y)
{
pDC->MoveTo(0, y);
pDC->LineTo(page_rc.right, y);
return;
}
VC++ Example, Visual C++ Example, MFC Example
|