diff --git a/Common/LCPrinter.cpp b/Common/LCPrinter.cpp new file mode 100644 index 0000000..067c2c9 --- /dev/null +++ b/Common/LCPrinter.cpp @@ -0,0 +1,495 @@ +/*=========================================================================== +==== ==== +==== ==== +============================================================================= +==== ==== +==== 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 +//============================================================================ +//============================================================================