📄 printdlg.cpp
字号:
void CPrintDlg::OnFilePrint()
{
CPrintInfo printInfo; //定义打印信息结构
ASSERT(printInfo.m_pPD != NULL);
/* 根据外部命令行创建一个打印DC */
if (LOWORD(GetCurrentMessage()->wParam) == ID_FILE_PRINT_DIRECT)
{
CCommandLineInfo* pCmdInfo = AfxGetApp()->m_pCmdInfo;
if (pCmdInfo != NULL)
{
if (pCmdInfo->m_nShellCommand == CCommandLineInfo::FilePrintTo)
{
printInfo.m_pPD->m_pd.hDC = ::CreateDC(pCmdInfo->m_strDriverName,
pCmdInfo->m_strPrinterName, pCmdInfo->m_strPortName, NULL);
if (printInfo.m_pPD->m_pd.hDC == NULL)
{
AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
return;
}
}
}
printInfo.m_bDirect = TRUE;
}
if (OnPreparePrinting(&printInfo))
{
// hDC必须有效,检查是否调用了DoPreparePrinting
ASSERT(printInfo.m_pPD->m_pd.hDC != NULL);
CString strOutput;
//如果是输出到文件,选择文件的名称
if (printInfo.m_pPD->m_pd.Flags & PD_PRINTTOFILE && !printInfo.m_bDocObject)
{
// 构建文件选择对话框
CString strDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULTEXT));
CString strPrintDef(MAKEINTRESOURCE(AFX_IDS_PRINTDEFAULT));
CString strFilter(MAKEINTRESOURCE(AFX_IDS_PRINTFILTER));
CString strCaption(MAKEINTRESOURCE(AFX_IDS_PRINTCAPTION));
CFileDialog dlg(FALSE, strDef, strPrintDef,
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, strFilter);
dlg.m_ofn.lpstrTitle = strCaption;
if (dlg.DoModal() != IDOK)//运行文件选择对话框
return;
//设置文件输出路径
strOutput = dlg.GetPathName();
}
// 设置文档信息
CString strTitle;
CDocument* pDoc = NULL;//在文档-视图框架结构中调用GetDocument();
if (pDoc != NULL)
strTitle = pDoc->GetTitle();
else
strTitle = m_SourceFile;
if (strTitle.GetLength() > 31)
strTitle.ReleaseBuffer(31);
DOCINFO docInfo;
memset(&docInfo, 0, sizeof(DOCINFO));
docInfo.cbSize = sizeof(DOCINFO);
docInfo.lpszDocName = strTitle;
CString strPortName;
int nFormatID;
if (strOutput.IsEmpty())//如果没有输出文件,即是通过打印机输出
{
docInfo.lpszOutput = NULL;
strPortName = printInfo.m_pPD->GetPortName();
nFormatID = AFX_IDS_PRINTONPORT;
}
else//通过文件输出
{
docInfo.lpszOutput = strOutput;
strPortName = strOutput;
nFormatID = AFX_IDS_PRINTTOFILE;
}
// 设置打印DC
CDC dcPrint;
if (!printInfo.m_bDocObject)
{
dcPrint.Attach(printInfo.m_pPD->m_pd.hDC); //CDC对象和打印dc关连
dcPrint.m_bPrinting = TRUE;
}
OnBeginPrinting(&dcPrint, &printInfo);
if (!printInfo.m_bDocObject)
dcPrint.SetAbortProc(_AfxAbortProc);
// 禁止主框架窗口
AfxGetMainWnd()->EnableWindow(FALSE);
// 开始启动打印过程
if (!printInfo.m_bDocObject && dcPrint.StartDoc(&docInfo) == SP_ERROR)
{
//出错,激活主框架窗口
AfxGetMainWnd()->EnableWindow(TRUE);
// 清理并显示错误信息
OnEndPrinting(&dcPrint, &printInfo);
dcPrint.Detach(); //CDC对象和打印dc分离
AfxMessageBox(AFX_IDP_FAILED_TO_START_PRINT);
return;
}
UINT nEndPage = printInfo.GetToPage();//得到绘制的结束页号
UINT nStartPage = printInfo.GetFromPage();//得到起始页号
//对起始页号和结束页号进行检查和调整,使之在有效范围
if (nEndPage < printInfo.GetMinPage())
nEndPage = printInfo.GetMinPage();
if (nEndPage > printInfo.GetMaxPage())
nEndPage = printInfo.GetMaxPage();
if (nStartPage < printInfo.GetMinPage())
nStartPage = printInfo.GetMinPage();
if (nStartPage > printInfo.GetMaxPage())
nStartPage = printInfo.GetMaxPage();
//设置打印时页的顺序,当结束页号大于起始页号时页号增加,返之是减少
int nStep = (nEndPage >= nStartPage) ? 1 : -1;
nEndPage = (nEndPage == 0xffff) ? 0xffff : nEndPage + nStep;
BOOL bError = FALSE;
if (printInfo.m_bDocObject)
{
OnPrepareDC(&dcPrint, &printInfo);
OnPrint(&dcPrint, &printInfo);
}
else
{
/*打印信息框*/
CPrintingDialog * pdlg = new CPrintingDialog(this);
pdlg->Create(IDD_PRINTING_DIALOG, this);
pdlg->ShowWindow(SW_SHOW);
pdlg->SetDlgItemText(IDC_PRINTING_INFO, "正在打印...");
//开始各页的打印循环
for (printInfo.m_nCurPage = nStartPage;
printInfo.m_nCurPage != nEndPage; printInfo.m_nCurPage += nStep)
{
OnPrepareDC(&dcPrint, &printInfo);
// 检查打印是否结束
if (!printInfo.m_bContinuePrinting)
break;
/*在此显示打印的当前页*/
CString temp;
temp.Format("当前打印第%d页", printInfo.m_nCurPage);
pdlg->SetDlgItemText(IDC_PRINTING_INFO, temp);
Sleep(1000);
// 设置打印区域为整个打印页面 (像素)
printInfo.m_rectDraw.SetRect(0, 0,
dcPrint.GetDeviceCaps(HORZRES),
dcPrint.GetDeviceCaps(VERTRES));
//转成逻辑坐标
dcPrint.DPtoLP(&printInfo.m_rectDraw);
// 试图启动打印当前页
if (dcPrint.StartPage() < 0)//如果当前页小于0
{
bError = TRUE;
break;
}
// 在新版本Windows中,必须调用 OnPrepareDC,因为
// StartPage 复位设置了设备描述属性.
OnPrepareDC(&dcPrint, &printInfo);//准备打印
ASSERT(printInfo.m_bContinuePrinting);
// 开始当前页的打印
OnPrint(&dcPrint, &printInfo);
if (dcPrint.EndPage() < 0 || !_AfxAbortProc(dcPrint.m_hDC, 0))
{
bError = TRUE;
break;
}
}
pdlg->DestroyWindow();//销毁正在打印对话框
delete pdlg;
}
// 清除文档打印过程
if (!printInfo.m_bDocObject)
{
if (!bError)
dcPrint.EndDoc();
else
dcPrint.AbortDoc();
}
AfxGetMainWnd()->EnableWindow(); // 激活主框架窗口
OnEndPrinting(&dcPrint, &printInfo);//打印完成后做清理工作
dcPrint.Detach(); //CDC对象和打印dc分离
}
}
BOOL CPrintDlg::OnPreparePrinting( CPrintInfo* pInfo )
{
return DoPreparePrinting(pInfo);
}
void CPrintDlg::OnBeginPrinting( CDC* pDC, CPrintInfo* pInfo )
{
if(!m_fSource.Open(m_SourceFile, CFile::modeRead | CFile::typeText))
{
MessageBox("打开文件失败!");
return;
}
m_PrintInfo = "开始打印...";
UpdateData(FALSE);
int line = 0;
CString sLine;
/*计算文件行数*/
while(m_fSource.ReadString(sLine))
line++;
m_fSource.SeekToBegin();
TEXTMETRIC textMetric;
pDC->GetTextMetrics(&textMetric);
int height = (line + 2) * textMetric.tmHeight + 20;//字体高
int screeny = pDC->GetDeviceCaps(VERTRES); //纸的高度(像素)
/*计算文件页数*/
UINT pages = height / screeny + (height%screeny==0 ? 0:1);
pInfo->SetMinPage(1);
if(pages < pInfo->GetMaxPage())
pInfo->SetMaxPage(pages);
m_nLine = (screeny - 20)/textMetric.tmHeight - 2;//计算每页要打印的文件行数
m_temp.Format("文件共%d页,打印%d页", pages, pInfo->GetMaxPage());
m_PrintInfo = m_temp;
UpdateData(FALSE);
}
void CPrintDlg::OnPrepareDC( CDC* pDC, CPrintInfo* pInfo )
{
m_PrintInfo.Format(",当前打印第%d页", pInfo->m_nCurPage);
m_PrintInfo = m_temp + m_PrintInfo;
UpdateData(FALSE);
}
void CPrintDlg::OnPrint( CDC* pDC, CPrintInfo* pInfo )
{
int line = 0;
CString sText;
CString csHeader;
char p1[30];//当前页的页码
sprintf(p1, "第 %d 页(共 %d 页)", pInfo->m_nCurPage, pInfo->GetMaxPage());
csHeader = p1;
POINT point;
point.x = 10;
point.y = 20;
TEXTMETRIC textMetric;
pDC->GetTextMetrics(&textMetric);
/*打印页码*/
pDC->TextOut(pDC->GetDeviceCaps(HORZRES)/2-csHeader.GetLength(), point.y, csHeader);
point.y += textMetric.tmHeight * 2;
/*每页打印m_nLine行*/
while(line < m_nLine && m_fSource.ReadString(sText))
{
pDC->TextOut(point.x, point.y, sText);
point.y += textMetric.tmHeight;
line++;
}
}
void CPrintDlg::OnEndPrinting( CDC* pDC, CPrintInfo* pInfo )
{
/*打印结束,关闭文件*/
m_fSource.Close();
m_PrintInfo.Format("打印过程结束,开始关闭");
UpdateData(FALSE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -