www.pudn.com > HReportTest.rar > HReportListPrint.cpp


// HReportListPrint.cpp: implementation of the CHReportListPrint class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "HReportListPrint.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
 
BOOL CHReportListPrint::OnPreparePrinting(CPrintInfo *pInfo) 
{ 
	ASSERT(m_pList != NULL); 
 
	pInfo->SetMinPage(1); 
	if(m_pList->GetItemCount() <= 0) 
		return FALSE; 
 
	CHeaderCtrl* pHeader = (CHeaderCtrl*) (m_pList->GetHeaderCtrl()); 
	ASSERT(pHeader != NULL); 
 
	const int nColCount = pHeader->GetItemCount(); 
	if (nColCount <= 0)  
		return FALSE; 
 
	m_pDx		= new int[nColCount+1]; 
	m_pFormat   = new int[nColCount]; 
	m_pColTitle = new char *[nColCount]; 
	ZeroMemory(m_pDx, sizeof(int) * (nColCount + 1)); 
	ZeroMemory(m_pFormat, sizeof(int) * nColCount); 
	ZeroMemory(m_pColTitle, sizeof(char *) * nColCount); 
 
	char txt[128]; 
	for (int i = 0; i < nColCount; ++i) 
	{ 
		HDITEM hi; 
		hi.cchTextMax = 128; 
		hi.pszText    = txt; 
 
		hi.mask = HDI_TEXT | HDI_WIDTH | HDI_FORMAT; 
		if (pHeader->GetItem(i, &hi)) 
		{ 
			m_pDx[i+1] = hi.cxy; 
			m_pFormat[i] = hi.fmt; 
			if (hi.cchTextMax > 0 && hi.pszText) 
			{ 
				m_pColTitle[i] = new char[hi.cchTextMax]; 
				ASSERT(m_pColTitle[i]); 
				lstrcpy(m_pColTitle[i], hi.pszText); 
			} 
		} 
	} 
	 
	return TRUE; 
} 
 
void CHReportListPrint::OnBeginPrinting(CDC *pDC, CPrintInfo *pInfo) 
{ 
	ASSERT(m_pList != NULL); 
 
	pInfo->m_rectDraw.SetRect(0, 0, pDC->GetDeviceCaps(HORZRES),  
									pDC->GetDeviceCaps(VERTRES)); 
	pDC->DPtoLP(pInfo->m_rectDraw); 
 
	// 创建字体 
//	m_fontPrint.CreatePointFont(m_nPrintSize * 10, m_strPrintName, pDC); 
	CreateFontX(m_fontPrint, pDC, m_strPrintName, m_nPrintSize, m_bPrintBold); 
	CreateFontX(m_fontHead, pDC, m_strHeadName, m_nHeadSize, m_bHeadBold); 
	CreateFontX(m_fontFoot, pDC, m_strFootName, m_nFootSize, m_bFootBold); 
 
	// 计算字体宽度 
	CString str = "H"; 
	CFont* oldFont = pDC->SelectObject(&m_fontPrint); 
	m_sizePrint = pDC->GetTextExtent(str); 
	pDC->SelectObject(&m_fontHead); 
	m_sizeHead  = pDC->GetTextExtent(str); 
	pDC->SelectObject(&m_fontFoot); 
	m_sizeFoot  = pDC->GetTextExtent(str); 
	pDC->SelectObject(oldFont); 
	m_sizePrint.cy += 4; 
	m_sizeHead.cy  += m_nHeadMargin; 
 
	// 计算列宽 
	const int nColCount = m_pList->GetHeaderCtrl()->GetItemCount(); 
	for (int i = 1; i <= nColCount; ++i)  
		m_pDx[i] += m_pDx[i-1]; 
 
	CRect rcPrint(pInfo->m_rectDraw); 
	SubtractMargin(pDC, rcPrint); 
	double db = rcPrint.Width(); 
	db /= (double) m_pDx[nColCount]; 
	for (i = 0; i <= nColCount; ++i)  
		m_pDx[i] = (int)double(m_pDx[i] * db); 
 
	// 计算 
	PrintListHead(pDC, rcPrint, TRUE); 
	PrintPageHead(pDC, rcPrint, TRUE); 
	CSize sz1 = PrintListFoot(pDC, rcPrint, TRUE); 
	CSize sz2 = PrintPageFoot(pDC, rcPrint, 0, 0, TRUE); 
	m_nFootHeight = sz1.cy + sz2.cy + 2; 
 
	// 计算总页数 
	m_nItemsOfPage = rcPrint.Height() / (m_sizePrint.cy + m_nLineSpace) - 1;	// 每页行数 
	int nPages = m_pList->GetItemCount() / m_nItemsOfPage + 1;	// 总页数 
	pInfo->SetMaxPage(nPages); 
} 
 
void CHReportListPrint::OnPrint(CDC *pDC, CPrintInfo *pInfo) 
{ 
	CRect rcPrint(pInfo->m_rectDraw); 
 
	SubtractMargin(pDC, rcPrint); 
	int nOldMode = pDC->SetBkMode(TRANSPARENT); 
 
	//打印页头 
	PrintPageHead(pDC, rcPrint, FALSE); 
 
	//打印表头 
	PrintListHead(pDC, rcPrint, FALSE); 
 
	int nFirst = (pInfo->m_nCurPage - 1) * m_nItemsOfPage; 
	int nLast  = (pInfo->m_nCurPage) * m_nItemsOfPage; 
 
	int y = rcPrint.top; 
	int x = rcPrint.left; 
 
	CFont * pOldFont = pDC->SelectObject(&m_fontPrint); 
	const int nMax = m_pList->GetItemCount(); 
	const int nColCount = m_pList->GetHeaderCtrl()->GetItemCount(); 
 
	CRect rc; 
	for (int i = nFirst; i < nLast; ++i) 
	{ 
		for (int t = 0; t < nColCount; ++t) 
		{ 
			rc.SetRect(	rcPrint.left + m_pDx[t] + m_nLeftMargin,  
						y,  
						rcPrint.left + m_pDx[t+1],  
						y + m_sizePrint.cy + m_nLineSpace); 
 
			if (i < nMax) 
			{ 
				UINT format = DT_LEFT; 
				if ( m_pFormat[t] & HDF_CENTER )  
					format = DT_CENTER; 
				else if ( m_pFormat[t] & HDF_RIGHT )  
					format = DT_RIGHT; 
 
				//打印单元格文字 
				pDC->DrawText(m_pList->GetItemText(i, t), rc, format| DT_VCENTER | DT_SINGLELINE); 
			} 
 
			//画单元格的左边和顶边 
			pDC->MoveTo(rc.left - m_nLeftMargin, rc.bottom); 
			pDC->LineTo(rc.left - m_nLeftMargin, rc.top); 
			pDC->LineTo(rc.right, rc.top); 
		} 
		//画一行的右边 
		pDC->LineTo(rc.right, rc.bottom+1); 
		y += m_sizePrint.cy + m_nLineSpace; 
	} 
 
	//画表格最下面的横线 
	pDC->MoveTo(rcPrint.left, y); 
	pDC->LineTo(rcPrint.right, y); 
	pDC->SelectObject(pOldFont); 
	 
	rcPrint = pInfo->m_rectDraw; 
	SubtractMargin(pDC, rcPrint); 
	rcPrint.top = rcPrint.bottom - m_nFootHeight; 
 
	PrintListFoot(pDC, rcPrint, FALSE); 
	PrintPageFoot(pDC, rcPrint, pInfo->m_nCurPage, (int) pInfo->GetMaxPage(), FALSE); 
	 
	pDC->SetBkMode(nOldMode); 
} 
 
#define SAFE_DELETE(p)  if(p) { delete p; p = NULL; } 
#define SAFE_DELETE_ARRAY(p)	if(p) { delete [] p; p = NULL; } 
 
void CHReportListPrint::OnEndPrinting(CDC *pDC, CPrintInfo *pInfo) 
{ 
	ASSERT(m_pList != NULL); 
 
	const int nColCount = m_pList->GetHeaderCtrl()->GetItemCount(); 
	if (nColCount > 0)  
	{ 
		SAFE_DELETE(m_pDx); 
		SAFE_DELETE_ARRAY(m_pFormat); 
		if (m_pColTitle) 
		{ 
			for (int i = 0; i < nColCount; ++i) 
				SAFE_DELETE_ARRAY(m_pColTitle[i]); 
			SAFE_DELETE_ARRAY(m_pColTitle); 
		} 
	} 
 
	m_fontPrint.Detach(); 
	m_fontHead.Detach(); 
	m_fontFoot.Detach(); 
} 
 
// 打印页头 
CSize CHReportListPrint::PrintPageHead(CDC* pDC, CRect& rcPage, BOOL bCalc) 
{ 
	CFont* pOldFont = pDC->SelectObject(&m_fontHead); 
	CSize sizePage(0,0); 
 
	//打印标题 
	if (!m_strPageHead.IsEmpty()) 
	{ 
		CRect rc(rcPage); 
		rc.bottom = rc.top + m_sizeHead.cy; 
		if ( bCalc ) 
			pDC->DrawText(m_strPageHead, rc, DT_CALCRECT | DT_CENTER); 
		else 
			pDC->DrawText(m_strPageHead, rc, DT_CENTER); 
 
		if (rc.Height() > sizePage.cy)  
			sizePage.cy = rc.Height(); 
	} 
 
	rcPage.top += sizePage.cy + m_nHeadMargin; 
	pDC->SelectObject(pOldFont); 
 
	return sizePage; 
} 
 
CSize CHReportListPrint::PrintPageFoot(CDC* pDC, CRect& rcPage, const int nPage,  
									   const int nMaxPage, BOOL bCalc) 
{ 
	CFont* pOldFont = pDC->SelectObject(&m_fontFoot); 
	CSize sizePage(0,0); 
 
	// 打印"第%d页 共%d页" 
	if (!m_strPageFormat.IsEmpty()) 
	{ 
		CString str; 
		str.Format(m_strPageFormat, nPage, nMaxPage); 
		CRect rc (rcPage); 
		rc.top = rc.bottom - m_sizeFoot.cy - 4; 
		if (bCalc)  
			pDC->DrawText(str, rc, DT_WORDBREAK | DT_CALCRECT | DT_CENTER); 
		else 
			pDC->DrawText(str, rc, DT_WORDBREAK | DT_CENTER); 
 
		sizePage.cy = rc.Height(); 
	} 
 
	rcPage.bottom -= sizePage.cy; 
	pDC->SelectObject(pOldFont); 
 
	return sizePage; 
} 
 
CSize CHReportListPrint::PrintListHead(CDC * pDC, CRect & rcPage, BOOL bCalc) 
{ 
	if (!bCalc) 
	{ 
		CFont* pOldFont = pDC->SelectObject(&m_fontPrint); 
		CRect rcc(rcPage.left, rcPage.top, rcPage.right, rcPage.top + m_sizePrint.cy); 
 
		const int nColCount = m_pList->GetHeaderCtrl()->GetItemCount(); 
 
		CRect rc; 
		CString str; 
		int y = rcPage.top; 
		for (int i = 0; i < nColCount; i++) 
		{ 
			rc.SetRect(	rcPage.left + m_pDx[i] + m_nLeftMargin,  
						y,  
						rcPage.left + m_pDx[i+1],  
						y + m_sizePrint.cy + m_nLineSpace); 
 
			str = m_pColTitle[i] ? m_pColTitle[i] : ""; 
 
			UINT format = DT_LEFT; 
			if ( m_pFormat[i] & HDF_CENTER )  
				format = DT_CENTER; 
			else if ( m_pFormat[i] & HDF_RIGHT )  
				format = DT_RIGHT; 
 
			pDC->DrawText(str, rc, format | DT_VCENTER | DT_SINGLELINE); 
 
			//画单元格的左边和顶边 
			pDC->MoveTo(rc.left - m_nLeftMargin, rc.bottom); 
			pDC->LineTo(rc.left - m_nLeftMargin, rc.top); 
			pDC->LineTo(rc.right, rc.top); 
		} 
		//画一行的右边 
		pDC->LineTo(rc.right, rc.bottom + 1); 
		pDC->SelectObject(pOldFont); 
	} 
 
	rcPage.top += m_sizePrint.cy + m_nLineSpace; 
	return CSize(0, m_sizePrint.cy); 
} 
 
CSize CHReportListPrint::PrintListFoot(CDC* pDC, CRect& rcPage, BOOL bCalc) 
{ 
	return CSize(0, 0); 
} 
 
void CHReportListPrint::SubtractMargin(CDC* pDC, CRect& rc) 
{ 
	CRect rcMarginMM = CRect(10, 10, 10, 10); 
 
	CSize sizeUp(rcMarginMM.left * 100, rcMarginMM.top * 100); 
	CSize sizeDown(rcMarginMM.right * 100, rcMarginMM.bottom * 100); 
 
	pDC->HIMETRICtoDP(&sizeUp); 
	pDC->HIMETRICtoDP(&sizeDown); 
 
	rc.top    += sizeUp.cy; 
	rc.left   += sizeUp.cx; 
	rc.right  -= sizeDown.cx; 
	rc.bottom -= sizeDown.cy; 
} 
 
//创建字体 
void CHReportListPrint::CreateFontX(CFont& font, CDC* pDC, const CString &strFont, int nSize, BOOL bBold) 
{ 
	//初始化 
	LOGFONT lf; 
	GetObject(GetStockObject(SYSTEM_FONT), sizeof(lf), &lf); 
	lf.lfWeight = bBold ? FW_BOLD : FW_NORMAL; 
 
	//更改字体 
	_tcscpy(lf.lfFaceName, strFont); 
 
	const int LOGY = pDC->GetDeviceCaps(LOGPIXELSY); 
 
	//更改大小 
	LOGFONT lf2; 
//	font.CreatePointFont(-MulDiv(nSize, -LOGY, 72), lf.lfFaceName, pDC); 
	font.CreatePointFont(nSize * 20, lf.lfFaceName, NULL); 
	font.GetLogFont(&lf2); 
	lf.lfHeight = lf2.lfHeight; 
	lf.lfWidth  = lf2.lfWidth; 
	lf.lfCharSet= lf2.lfCharSet; 
 
	font.DeleteObject(); 
	BOOL bCreated = font.CreateFontIndirect(&lf); 
	ASSERT(bCreated); 
}