⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 printdlg.cpp

📁 Visual C++_ 600 编程学习捷径
💻 CPP
📖 第 1 页 / 共 2 页
字号:
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 + -