📄 lcprint.cpp
字号:
#include "stdafx.h"
#include "LCPrint.h"
#define LEFT_MARGIN 2
#define RIGHT_MARGIN 4
#define HEADER_HEIGHT 4
#define FOOTER_HEIGHT 3
//Set it all to 0
//********************************CONSTRUCTOR************************************
CListPrinting::CListPrinting()
{
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;
}
//Using default for printer guess at # of pages.
//If no printer exists return FALSE;
//************************ONPREPAREPRINTING*******************************
BOOL CListPrinting::OnPreparePrinting(CPrintInfo* pInfo, CView * cview, CListCtrl * t_lc)
{
if(t_lc==NULL || pInfo == NULL) return FALSE;
lc = t_lc;//Set Pointer to list Control
//Lets make a guess as to how many pages there are based on the default printer.
CPrintDialog pdlg(FALSE);
if (!pdlg.GetDefaults()) return FALSE;//If no defaults then no printer!!
CDC t_pDC;
t_pDC.Attach(pdlg.GetPrinterDC());
compute_metrics(&t_pDC);
m_nMaxRowCount = lc->GetItemCount(); if(!m_nMaxRowCount) return FALSE;//Get the number of rows
int nMaxPage = m_nMaxRowCount/m_nRowsPerPage + 1;
pInfo->SetMaxPage(nMaxPage);
pInfo->m_nCurPage = 1; // start printing at page# 1
//If you want to be able to do this remove it.
pInfo->m_pPD->m_pd.Flags |=PD_HIDEPRINTTOFILE;
if (cview)
return cview->DoPreparePrinting(pInfo);
else
return TRUE;
}
//Call this from your view class OnBeingPrinting function
//*************************ONBEGINGPRINTING*************************
void CListPrinting::OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo, CString & t_title, CString & t_date)
{
if(pDC == NULL || pInfo==NULL)
return;
TitleStr = t_title;
DateStr = t_date;
//create lc font, and Bold lc Font
LOGFONT lf;
CFont * lcfont_ptr = lc->GetFont();
lcfont_ptr->GetLogFont(&lf);
lcFont.CreateFontIndirect(&lf);
lf.lfWeight = FW_BOLD;
lf.lfHeight+=22;//Make it a little bigger
lf.lfWidth = 0;
BoldFont.CreateFontIndirect(&lf);
compute_metrics(pDC);
int nMaxPage = m_nMaxRowCount/m_nRowsPerPage + 1;//Compute this again in case user changed printer
pInfo->SetMaxPage(nMaxPage);
pInfo->m_nCurPage = 1; // start printing at page# 1
return;
}
//***********************ONPRINT*************************
void CListPrinting::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
if(NULL == pDC || NULL == pInfo)
return;
//This has to be in OnPrint() or else PrintPreview goes screwy
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;
PrintHeader(pDC, pInfo); //print the header
pDC->SetWindowOrg(-1*page_rc.left, 0);
PrintFooter(pDC, pInfo); //Print the footer
pDC->SetWindowOrg(-1*page_rc.left, -1*HEADER_HEIGHT*m_nRowHeight);
PrintHeaderControl(pDC, pInfo);//Print the header Control, Manually
pDC->SelectObject(&lcFont);//Use the LC normal font
pDC->SetTextColor(RGB(0,0,0));//Black text on
pDC->SetBkColor(RGB(255,255,255));//White paper
CRect rcBounds;
lc->GetItemRect(nStartRow, &rcBounds, LVIR_BOUNDS);
//offset top margin of rcBounds by ListControl header
CRect rc;
lc->GetHeaderCtrl()->GetClientRect(&rc);
rcBounds.OffsetRect(0, -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);
pDC->SelectObject(pOldFont);//Put the old font back
return;
}
//Set the extents after calling this function because it uses printer extents
//He is using a list in here have to figure out what to do.
//********************************PRINT_HEADER************************************
void CListPrinting::PrintHeader(CDC *pDC, CPrintInfo *pInfo)
{
pDC->SelectObject(&BoldFont);
pDC->SetTextColor(RGB(0,0,0));//Black text on
pDC->SetBkColor(RGB(255,255,255));//White paper
CRect rc = page_rc;
rc.bottom = rc.top+m_nRowHeight;
//print App title on top right margin
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
//****************************PRINT_FOOTER****************************************
void CListPrinting::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); //draw line
//draw page number
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);
//Now draw the DateStr at bottom of page
pDC->DrawText(DateStr,-1,rc, DT_RIGHT | DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER);
return;
}
//Do the cleanup
//********************ONEND_PRINTING*****************
void CListPrinting::OnEndPrinting(CDC* pDC, CPrintInfo* pInfo)
{
lcFont.DeleteObject();
BoldFont.DeleteObject();
return;
}
//This function sets alls of the row and metric member vars
//************************COMPUTE_METRICS*********************
void CListPrinting::compute_metrics(CDC *pDC)
{
//This includes width for all columns
CRect row_rc; lc->GetItemRect(0, &row_rc, LVIR_BOUNDS);
//Get the list control window DC
CDC *pCtlDC = lc->GetDC(); if(NULL == pCtlDC) 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);
lc->ReleaseDC(pCtlDC);
//Set up a page rc in list control units that accounts for left and right margins
page_rc.SetRect(0,0, pDC->GetDeviceCaps(HORZRES), pDC->GetDeviceCaps(VERTRES));
page_rc.bottom = page_rc.bottom/m_ratioy;//Convert units to List Control
page_rc.right = page_rc.right/m_ratiox;
page_rc.left = LEFT_MARGIN*tm.tmAveCharWidth;//adjust sides for magins
page_rc.right -= RIGHT_MARGIN*tm.tmAveCharWidth;
m_nRowHeight = row_rc.Height();//Get the height of a row.
int pRowHeight = (int)(m_nRowHeight*m_ratioy);//Get RowHeight in printer units.
m_nRowsPerPage = pDC->GetDeviceCaps(VERTRES)/pRowHeight;//How many rows will fit on page?
m_nRowsPerPage -= (HEADER_HEIGHT+FOOTER_HEIGHT);//After header and footer rows
m_nRowsPerPage -= 1; //After header Control row
return;
}
//You can't just have the header control print itself. 1st of all it looks crappy.
//2nd if part of header control is off screen does not print itself.
//So we will manually print it.
//************************PRINTHEADERCONTROL****************************
void CListPrinting::PrintHeaderControl(CDC *pDC, CPrintInfo *pInfo)
{
UINT dtFlags = DT_SINGLELINE|DT_NOPREFIX|DT_VCENTER|DT_LEFT;//drawing flags
CHeaderCtrl* hc = lc->GetHeaderCtrl();
hc_items = hc->GetItemCount();
if (hc_items < 1) return; //Remember that hc_items is also used to draw rows.
int order_array[30];//Shouln't have more than 30 columns
hc->GetOrderArray(order_array, hc_items);
char temp_str[1024];
HDITEM phi;
phi.mask = 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);//Get in viewed order
rc.right += phi.cxy;
pDC->DrawText(temp_str, -1, rc, dtFlags);
rc.left += phi.cxy;
}
//Now draw the line below header control
draw_line_at(pDC, rc.bottom);
return;
}
//*************************************DRAWROW********************************************
void CListPrinting::DrawRow(CDC *pDC, int nItem)
{
if (hc_items < 1) //Then nothing to print
return;
int order_array[30];//Shouln't have more than 30 columns
lc->GetColumnOrderArray(order_array, hc_items);
CString temp_str;
LV_COLUMN lvc;
lvc.mask = LVCF_WIDTH;
CRect rc; lc->GetItemRect(nItem, rc, LVIR_BOUNDS);
int offset = pDC->GetTextExtent(" ", 1).cx;//Returns CSIZE so get cx member of CSIZE object.
rc.left += offset/2;//This makes it so that label will be over a little bit
rc.right -= offset;//Just keep this stuff it DOES look better.
for (int i = 0; i < hc_items; i++)
{
lc->GetColumn(order_array[i], &lvc);//Get in viewed order
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);//draw a line below each row
rc.left += lvc.cx;
}
return;
}
//Just pass this function a y position to draw the line at.
//*************************DRAW_LINE_AT************************************
void CListPrinting::draw_line_at(CDC *pDC, unsigned int y)
{
pDC->MoveTo(0, y);
pDC->LineTo(page_rc.right, y);//Use the page_rc to figure out the width of the line
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -