最近尝试使用pdflib输出pdf文档,但是pdflib的方法很多,要将打印输出与pdf匹配,需要编写很多代码,而且一旦需要修改,也是个麻烦事,所以就想了个偷懒的办法,如下:
1、在项目中加入pdflib支持,具体方法就不赘述了,网上有很多。
2、添加几个变量:
BOOL m_bPrintAsPdf; // 是否输出pdf,初始化为FALSE
CString m_strPdfFileName;
HANDLE m_hPdfDevMode;
HANDLE m_hPdfDevNames;
3、在输出pdf文档的响应函数中:
if(m_hPdfDevMode == NULL || m_hPdfDevNames == NULL)
{ // 使用windows自带的虚拟打印机作为输出媒介,如果没有可以手动安装,但是名称要一致
GetPrinterDevice(_T("Microsoft XPS Document Writer"), &m_hPdfDevNames, &m_hPdfDevMode);
}
TCHAR BASED_CODE szFilter[] = _T("PDF Files(*.pdf)|*.pdf||");
CFileDialog OpenFileDlg(FALSE,
_T("pdf"),
_T(""),
OFN_HIDEREADONLY,
szFilter,
this);
if(OpenFileDlg.DoModal() == IDCANCEL) return;
m_strPdfFileName = OpenFileDlg.GetPathName();
m_bPrintAsPdf = TRUE;
CMyView::OnFilePrint();
return;
4、在OnPreparePrinting函数中改成:
if(m_bPrintAsPdf)
{
PRINTDLG pd;
AfxGetApp()->GetPrinterDeviceDefaults(&pd);
AfxGetApp()->SelectPrinter(m_hPdfDevNames, m_hPdfDevMode, FALSE);
pInfo->m_bDirect = TRUE;
pInfo->m_pPD->m_pd.Flags |= PD_PRINTSETUP | PD_RETURNDC;
// Perform default MFC handling.
BOOL b = DoPreparePrinting(pInfo);
// Reinstall MFC's printer.
AfxGetApp()->SelectPrinter(pd.hDevNames, pd.hDevMode, FALSE);
pInfo->m_bDirect = FALSE;
return b;
}
else
return DoPreparePrinting(pInfo);
5、在OnPrint函数中:
if(m_bPrintAsPdf)
{
CRect rectClient = pInfo->m_rectDraw;
CDC memDC;
memDC.CreateCompatibleDC(pDC);
CBitmap bmp;
bmp.CreateCompatibleBitmap(pDC, rectClient.Width(), rectClient.Height());
CBitmap* pOldBmp = memDC.SelectObject(&bmp);
memDC.FillSolidRect(rectClient, RGB(255,255,255));
// PrintOut就是打印输出函数
PrintOut(&memDC, pInfo);
// 下面将每一页保存成图片
CImage TempImageObj;
TempImageObj.Attach((HBITMAP)bmp.Detach());
CString strPngFile;
// AppDirectory是我的应用程序所在路径,获取方法这里不再描述
strPngFile.Format("%s\\temp%d.png", AppDirectory, pInfo->m_nCurPage);
if(E_FAIL == TempImageObj.Save(strPngFile))
{
DWORD dwError = GetLastError();
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), NULL, (LPTSTR) &lpMsgBuf, 0, NULL );
MessageBox((LPCTSTR)lpMsgBuf, "ERROR", MB_OK | MB_ICONINFORMATION);
LocalFree( lpMsgBuf );
}
memDC.SelectObject(pOldBmp);
ReleaseDC(&memDC);
// 所有图片全部生成,要保存到pdf文件了
if(pInfo->m_nCurPage == pInfo->GetMaxPage())
{
m_bPrintAsPdf = FALSE;
char szPdfFileName[500], szPngFileName[500];
sprintf_s(szPdfFileName, 500, _T("%s"), m_strPdfFile);
PDFlib pdf;
float fTemp,fMaxData=0,fMinlength;
pdf.set_parameter("license", "w700602-009100-731090-Y6WPH2-5SE4A2");
if(pdf.open_file(szPdfFileName) == -1)
MessageBox("打开文件出错!");
pdf.set_info("Creator", "admin");
pdf.set_info("Author", "my home");
pdf.set_info("Title", "Convert to PDF");
pdf.set_info("Subject", "PDF Creator");
int i;
for(i = 0; i < pInfo->GetMaxPage(); i++)
{
strPngFile.Format("%s\\temp%d.png", AppDirectory, i + 1);
sprintf_s(szPngFileName, 500, _T("%s"), strPngFile);
int iImage = pdf.load_image("png", szPngFileName, "");
if(iImage == -1)
{
MessageBox("Save pdf file failed!");
break;
}
pdf.begin_page_ext(rectClient.Width(), rectClient.Height(), "");
pdf.place_image(iImage, 0, 0, 1);
pdf.end_page_ext("");
// 将临时图片文件删除
DeleteFile(szPngFileName);
}
pdf.close();
}
return;
}
else
PrintOut(pDC, pInfo);
试了下,效果还不错。PS: 当然可以使用各种pdf虚拟打印机,不过放在安装包里也不方便,所以我选择了这种方式。