Files
HLStock/Common/LCPrinter.cpp
2013-07-20 23:27:28 +00:00

496 lines
15 KiB
C++

/*===========================================================================
==== ====
==== ====
=============================================================================
==== ====
==== File : LCPrinter.cpp ====
==== Project name : ====
==== Project number : ====
==== Creation date : 10/08/2000 ====
==== ====
==== ====
=============================================================================
===========================================================================*/
//============================================================================
// Inclusions
//============================================================================
#include "stdafx.h"
#include "LCPrinter.h"
//============================================================================
// Constants
//============================================================================
const int LEFT_MARGIN = 4;
const int RIGHT_MARGIN = 8;
const int HEADER_HEIGHT = 2;
const int FOOTER_HEIGHT = 2;
//============================================================================
// Data types
//============================================================================
//============================================================================
// Variables
//============================================================================
//============================================================================
// Development tools
//============================================================================
//============================================================================
// Templates and global functions
//============================================================================
//============================================================================
//============================================================================
// class CLCPrinter
//============================================================================
//============================================================================
/*============================================================================
Description: Constructor.
============================================================================*/
CLCPrinter::CLCPrinter()
{
m_nRowHeight = 0;
m_nRowsPerPage = 0;
m_nMaxRowCount = 0;
m_ratiox = 0;
m_ratioy = 0;
m_hcItems = 0;
m_pLC = NULL;
m_pOldFont = NULL;
m_page_rc.SetRect(0,0,0,0);
}
/*============================================================================
Description: Sets alls of the row and metric member variables
Retour: -
============================================================================*/
void CLCPrinter::ComputeMetrics(CDC *pDC)
{
// This includes width for all columns
CRect row_rc;
m_pLC->GetItemRect(0, &row_rc, LVIR_BOUNDS);
// Get the list control window DC
CDC* pCtlDC = m_pLC->GetDC();
if (pCtlDC == NULL) {
return;
}
// so we can get the avg character width
TEXTMETRIC tm;
pCtlDC->GetTextMetrics(&tm);
// Lets get the ratios for scaling to printer DC
// Fit all columns to 1 page, regardless of column number.
m_ratiox = pDC->GetDeviceCaps(HORZRES)/(row_rc.Width() + (LEFT_MARGIN+RIGHT_MARGIN)*tm.tmAveCharWidth);
// width of pDC/whats got to fit into it in lcDC units
m_ratioy = pDC->GetDeviceCaps(LOGPIXELSY)/pCtlDC->GetDeviceCaps(LOGPIXELSY);
m_pLC->ReleaseDC(pCtlDC);
// Set up a page rc in list control units that accounts for left and right margins
m_page_rc.SetRect(0, 0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
// Convert units to List Control
m_page_rc.bottom = m_page_rc.bottom / m_ratioy;
m_page_rc.right = m_page_rc.right / m_ratiox;
// Adjust sides for magins
m_page_rc.left = LEFT_MARGIN * tm.tmAveCharWidth;
m_page_rc.right -= RIGHT_MARGIN * tm.tmAveCharWidth;
// Get the height of a row.
m_nRowHeight = row_rc.Height();
// Get RowHeight in printer units.
int pRowHeight = (int)(m_nRowHeight * m_ratioy);
// How many rows will fit on page?
m_nRowsPerPage = pDC->GetDeviceCaps(VERTRES)/pRowHeight;
// After header and footer rows
m_nRowsPerPage -= (HEADER_HEIGHT*2+FOOTER_HEIGHT);
//After header Control row
m_nRowsPerPage -= 1;
}
/*============================================================================
Description: Draw a horizontal line at the specified position
pDC: See MFC
y: Y-Axis position at which the line is to be drawned
Retour: -
============================================================================*/
void CLCPrinter::DrawLineAt(CDC *pDC, unsigned int y)
{
//Use the m_page_rc to figure out the width of the line
pDC->MoveTo(0, y);
pDC->LineTo(m_page_rc.right, y);
}
/*============================================================================
Description: Draw a row of the list control
pDC: See MFC
nItem: Index of the item to be printed
Retour: -
============================================================================*/
void CLCPrinter::DrawRow(CDC *pDC, int nItem)
{
// If nothing to print, return
if (m_hcItems < 1) {
return;
}
// Shouln't have more than 30 columns
int order_array[30];
m_pLC->GetColumnOrderArray(order_array, m_hcItems);
CRect rc;
CString temp_str;
LV_COLUMN lvc;
lvc.mask = LVCF_WIDTH;
m_pLC->GetItemRect(nItem, rc, LVIR_LABEL);
int offset = pDC->GetTextExtent(_T(" "), 1).cx;
// This makes it so that label will be over a little bit
rc.left += offset / 2;
// Just keep this stuff it DOES look better.
rc.right -= offset;
for (int i = 0; i < m_hcItems; i++) {
// Get in viewed order
m_pLC->GetColumn(order_array[i], &lvc);
temp_str = m_pLC->GetItemText(nItem, order_array[i]);
rc.right += lvc.cx;
pDC->DrawText(temp_str, -1, rc, DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER|DT_LEFT);
// Draw a line below each row
DrawLineAt(pDC, rc.bottom);
rc.left += lvc.cx;
}
}
/*============================================================================
Description: See MFC
Retour: -
============================================================================*/
void CLCPrinter::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo, const CString& titleStr, const CString& dateStr)
{
if (pDC == NULL || pInfo == NULL) {
return;
}
m_titleStr = titleStr;
m_dateStr = dateStr;
// Create listcontrol font, and bold listcontrol font
LOGFONT lf;
CFont* pFont = m_pLC->GetFont();
pFont->GetLogFont(&lf);
m_lcFont.CreateFontIndirect(&lf);
lf.lfWidth = 0;
lf.lfWeight = FW_BOLD;
// Make it a little bigger
lf.lfHeight+= 22;
m_boldFont.CreateFontIndirect(&lf);
// Compute this again in case user changed printer
ComputeMetrics(pDC);
int nMaxPage = m_nMaxRowCount/m_nRowsPerPage + 1;
pInfo->SetMaxPage(nMaxPage);
// Start printing at first page
pInfo->m_nCurPage = 1;
}
/*============================================================================
Description: See MFC
Retour: -
============================================================================*/
void CLCPrinter::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)
{
m_lcFont.DeleteObject();
m_boldFont.DeleteObject();
}
/*============================================================================
Description: See MFC
Retour: -
============================================================================*/
BOOL CLCPrinter::OnPreparePrinting(CPrintInfo* pInfo, CView* pView, CListCtrl* pLC)
{
if (pLC == NULL || pView == NULL || pInfo == NULL) {
return FALSE;
}
// Set Pointer to list Control
m_pLC = pLC;
// Lets make a guess as to how many pages there are based on the default printer.
CPrintDialog dlg(FALSE);
if (!dlg.GetDefaults()) {
//If no defaults then no printer!!
return FALSE;
}
CDC dc;
dc.Attach(dlg.GetPrinterDC());
ComputeMetrics(&dc);
// Get the number of rows
m_nMaxRowCount = m_pLC->GetItemCount();
if (!m_nMaxRowCount) {
return FALSE;
}
int nMaxPage = m_nMaxRowCount/m_nRowsPerPage + 1;
pInfo->SetMaxPage(nMaxPage);
// Start printing at first page
pInfo->m_nCurPage = 1;
// If you want to be able to do this remove it.
pInfo->m_pPD->m_pd.Flags |= PD_HIDEPRINTTOFILE;
return pView->DoPreparePrinting(pInfo);
}
/*============================================================================
Description: See MFC
Retour: -
============================================================================*/
void CLCPrinter::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
if (pDC == NULL || pInfo == NULL) {
return;
}
// This has to be in OnPrint() or else PrintPreview goes screwy
m_pOldFont = pDC->GetCurrentFont();
// Fit all columns to 1 page, regardless of column number.
pDC->SetMapMode(MM_ANISOTROPIC);
// For every 1 List Control pixel
pDC->SetWindowExt(1, 1);
// The printer has ratio more dots
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;
}
// Print the header
pDC->SetWindowOrg(-1 * m_page_rc.left, 0);
PrintHeader(pDC, pInfo);
// Print the footer
PrintFooter(pDC, pInfo);
pDC->SetWindowOrg(-1 * m_page_rc.left, -1 * HEADER_HEIGHT * m_nRowHeight);
// Print the header Control manually
PrintHeaderControl(pDC, pInfo);
// Use the LC normal font
pDC->SelectObject(&m_lcFont);
// Black text on white paper
pDC->SetTextColor(RGB(0, 0, 0));
pDC->SetBkColor(RGB(255, 255, 255));
CRect rcBounds;
m_pLC->GetItemRect(nStartRow, &rcBounds, LVIR_BOUNDS);
// Offset top margin of rcBounds by ListControl header
CRect rc;
m_pLC->GetHeaderCtrl()->GetClientRect(&rc);
rcBounds.OffsetRect(0, -1 * rc.Height());
pDC->OffsetWindowOrg(rcBounds.left, rcBounds.top);
// Start printing rows
for (int i = nStartRow; i < nEndRow; i++) {
DrawRow(pDC, i);
}
// SetWindowOrg back for next page
pDC->SetWindowOrg(0,0);
// Put the old font back
pDC->SelectObject(m_pOldFont);
}
/*============================================================================
Description: Print the page footer with a line and a date, and page number
pDC: See MFC
pInfo: See MFC
Retour: -
============================================================================*/
void CLCPrinter::PrintFooter(CDC *pDC, CPrintInfo *pInfo)
{
CRect rc = m_page_rc;
rc.top = rc.bottom - FOOTER_HEIGHT * m_nRowHeight;
rc.bottom = rc.top + m_nRowHeight + FOOTER_HEIGHT;
// Draw line
DrawLineAt(pDC, rc.top);
DrawLineAt(pDC, rc.top + 1);
DrawLineAt(pDC, rc.top + 2);
// Draw page number
CString sTemp ;
rc.OffsetRect(0, m_nRowHeight/2);
sTemp.Format(_T("Page %d - %d"), pInfo->m_nCurPage, pInfo->GetMaxPage());
pDC->DrawText(sTemp, -1, rc, DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
// Now draw the date at bottom of page
rc.left = 0;
pDC->DrawText(m_dateStr, -1, rc, DT_LEFT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
}
/*============================================================================
Description: Print the page header
pDC: See MFC
pInfo: See MFC
Retour: -
============================================================================*/
void CLCPrinter::PrintHeader(CDC *pDC, CPrintInfo *pInfo)
{
pDC->SelectObject(&m_boldFont);
//Black text on white paper
pDC->SetTextColor(RGB(0, 0, 0));
pDC->SetBkColor(RGB(255, 255, 255));
CRect rc = m_page_rc;
rc.bottom = rc.top + m_nRowHeight + HEADER_HEIGHT;
//Use the m_page_rc to figure out the width of the line
DrawLineAt(pDC, rc.bottom + 1);
DrawLineAt(pDC, rc.bottom + 2);
DrawLineAt(pDC, rc.bottom + 3);
// Print App title on top left margin
pDC->DrawText(m_titleStr, &rc, DT_SINGLELINE | DT_NOPREFIX | DT_VCENTER | DT_LEFT | DT_NOCLIP);
}
/*============================================================================
Description: Print the list control header
pDC: See MFC
pInfo: See MFC
Retour: -
============================================================================*/
void CLCPrinter::PrintHeaderControl(CDC *pDC, CPrintInfo *pInfo)
{
CHeaderCtrl* hc = m_pLC->GetHeaderCtrl();
// Drawing flags
UINT dtFlags = DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER|DT_LEFT;
m_hcItems = hc->GetItemCount();
// Remember that m_hcItems is also used to draw rows.
if (m_hcItems < 1) {
return;
}
// Shouln't have more than 30 columns
int order_array[30];
hc->GetOrderArray(order_array, m_hcItems);
TCHAR temp_str[1024];
HDITEM phi;
phi.cchTextMax = 1024;
phi.mask = HDI_TEXT | HDI_WIDTH;
phi.pszText = temp_str;
CRect rc(0, 0, 0, m_nRowHeight);
for (int i = 0; i < m_hcItems; i++) {
// Get in viewed order
hc->GetItem(order_array[i], &phi);
rc.right += phi.cxy;
pDC->DrawText(temp_str, -1, rc, dtFlags);
rc.left += phi.cxy;
}
// Now draw the line below header control
DrawLineAt(pDC, rc.bottom);
}
//============================================================================
//============================================================================
// Test section
//============================================================================
//============================================================================