2011-07-06 15:27 4人阅读 评论(0) 收藏 编辑 删除
声明:此功能非原创,笔者只是在原创的基础上改进了一些,以达到开发项目的目的。
以下的内容,可能有些人见过,但既然我贴在这儿,就肯定有一些东西,你没见过,本文主要实现图文打印。
在MFC下实现打印步骤:
/****
本文提供的CPrintFrame和CPrintView类是连个可重用的类,开发者只需要把这两个类对应的四个文件拷贝到工程文件所在目录中(PrintFrame.h,PringtView.h,PrintFrame.cpp,PrintView.cpp),并将这四个文件加入工程,并在需要执行打印功能的代码处加入
#include “PrintFrame.h”
#include “PrintView.h”
1. 建立一个CPrintFrame的对象,设该对象的指针为pFrame,并将对话框的指针传给该对象的m_pCallerDlg,即pFrame->m_pCallerDlg = this;
2. 调用对象的Create函数创建框架窗口;例如pFrame->Create(NULL,"频谱打印",WS_OVERLAPPEDWINDOW,CRect(0,0,0,0));
3. 如果要执行打印,则调用pFrame->m_pView->OnMyPrint();
4. 如果要执行打印预览,则调用:
pFrame->m_pView->OnMyPrintPreview();
例如:
void CDlgPrintDlg::OnPrint() //执行打印功能
{
CPrintFrame *pFrame = new CPrintFrame;
pFrame->m_pCallerDlg = this;
pFrame->Create(NULL,"Curve
Print",WS_OVERLAPPEDWINDOW,CRect(0,0,0,0));
pFrame->m_pView->OnMyPrint();
}
void CDlgPrintDlg::OnPrintPreview() //执行打印预览功能
{
CPrintFrame *pFrame = new CPrintFrame;
pFrame->m_pCallerDlg = this;
pFrame->Create(NULL,"Curve Print
Preview",WS_OVERLAPPEDWINDOW,CRect(0,0,0,0));
pFrame->m_pView->OnMyPrintPreview();
}
5. 在对话框中响应 WM_BEGIN_PRINTING, WM_END_PRINTING,WM_MY_PRINT消息,分别完成打印的初始化,释放和具体的打印操作;
如在示例程序中添加了三个消息响应函数来执行该功能。
ON_MESSAGE(WM_BEGIN_PRINTING,OnBeginPrinting)
ON_MESSAGE(WM_END_PRINTING,OnEndPrinting)
ON_MESSAGE(WM_MY_PRINT,OnMyPrint)
其中OnMyPrint是跟具体要打印什么内容有关的开发人员要重点完成的代码,可以打印表格,图片,数据,只要GDI绘图可以进行的操作在这里都可以完成。由于打印预览的一部分工作在CView类里完成,因此在用户程序中只需要相应WM_MY_PRINT消息就可以执行打印预览的功能,而不需要另外编写打印预览代码。
然后按照上述5个步骤进行即可以实现一个功能完整的打印程序,利用上述类实现对话框打印不但节省开发者许多时间,而且功能很强大,能达到很专业的水平,但是该方法有一个缺点,笔者发现如果开发者使用静态连接的MFC库时则会出错,只适用于Use MFC in a Shelled DLL情况,而且必须使程序为Debug版本的。
下面说一下我是如何向OnMyPrint(WPARAM wParam,LPARAM lParam)添加代码
第一个参数,传递的是句柄,第二个参数。。。没用到。。
先看下打印预览的效果吧:
下面再解释下实现的代码:
intnWidth=pDC->GetDeviceCaps(HORZRES);
intnHeight=pDC->GetDeviceCaps(VERTRES);
intghdf=pDC->GetDeviceCaps(LOGPIXELSY);
LRESULT CExamineeyeDlg::OnMyPrint(WPARAMwParam,LPARAM lParam)
{
CDC* pDC =(CDC*)wParam;
CFont font;//字体类型
CFont *oldfont;
CPoint point;
CString ss="在对话框中使用打印预览";
intnWidth=pDC->GetDeviceCaps(HORZRES);//得到纸张的宽度
intnHeight=pDC->GetDeviceCaps(VERTRES);//得到纸张的宽度
intghdf=pDC->GetDeviceCaps(LOGPIXELSY);//得到纸张的像素dpi
CRectDrawRect(0,0,nWidth,nHeight),rect,tempRect,tempRect1;
DrawRect.InflateRect(-100,-nHeight/8,-100,-50);//InflateRect函数增大或减小指定矩形的宽和高
//参数的顺序为左上右下
pDC->Rectangle(&DrawRect); //画矩形
tempRect1=tempRect;
font.CreateFont(-MulDiv(25,-pDC->GetDeviceCaps(LOGPIXELSY),72),
0,0,0,FW_NORMAL,0,0,0,GB2312_CHARSET,
OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,
VARIABLE_PITCH|FF_SWISS,_T("幼圆"));//25为字体大小
oldfont=pDC->SelectObject(&font);//设置字体
tempRect=DrawRect;
tempRect.InflateRect(0,nHeight/12,0,0);
pDC->DrawText(str1[9],&tempRect,DT_CENTER|DT_TOP|DT_SINGLELINE);//将文字绘出来
//pDC->SelectObject(oldfont);
font.DeleteObject();//需要删除font,以重新分配内存
font.CreateFont(-MulDiv(18,-pDC->GetDeviceCaps(LOGPIXELSY),72),
0,0,0,FW_NORMAL,0,0,0,GB2312_CHARSET,
OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,
VARIABLE_PITCH|FF_SWISS,_T("黑体"));
pDC->SelectObject(&font);
tempRect.InflateRect(0,-nHeight/20,0,0);
pDC->DrawText(str1[8],&tempRect,DT_CENTER|DT_TOP|DT_SINGLELINE);
font.DeleteObject();
font.CreateFont(-MulDiv(12,-pDC->GetDeviceCaps(LOGPIXELSY),72),
0,0,0,FW_NORMAL,0,0,0,GB2312_CHARSET,
OUT_STROKE_PRECIS,CLIP_STROKE_PRECIS,DRAFT_QUALITY,
VARIABLE_PITCH|FF_SWISS,_T("宋体"));
pDC->SelectObject(&font);
tempRect.InflateRect(-100,-nHeight/24,-300,0);
pDC->MoveTo(DrawRect.left,DrawRect.top+(DrawRect.bottom-DrawRect.top)/28);//这一条和下面一条来实现画线
pDC->LineTo(DrawRect.right,DrawRect.top+(DrawRect.bottom-DrawRect.top)/28);//
pDC->DrawText(str1[0],&tempRect,DT_LEFT|DT_TOP|DT_SINGLELINE);//其中DT_LEFT表示左对齐
pDC->DrawText(str1[1],&tempRect,DT_CENTER|DT_TOP|DT_SINGLELINE);
pDC->DrawText(str1[2],&tempRect,DT_RIGHT|DT_TOP|DT_SINGLELINE);
tempRect.InflateRect(0,-nHeight/30,0,0);
pDC->MoveTo(DrawRect.left,DrawRect.top+(DrawRect.bottom-DrawRect.top)/28*2);
pDC->LineTo(DrawRect.right,DrawRect.top+(DrawRect.bottom-DrawRect.top)/28*2);
pDC->DrawText(str1[3],&tempRect,DT_LEFT|DT_TOP|DT_SINGLELINE);
pDC->DrawText(str1[4],&tempRect,DT_CENTER|DT_TOP|DT_SINGLELINE);
pDC->DrawText(str1[5],&tempRect,DT_RIGHT|DT_TOP|DT_SINGLELINE);
tempRect.InflateRect(0,-nHeight/30,0,0);
pDC->MoveTo(DrawRect.left,DrawRect.top+(DrawRect.bottom-DrawRect.top)/28*3);
pDC->LineTo(DrawRect.right,DrawRect.top+(DrawRect.bottom-DrawRect.top)/28*3);
pDC->DrawText(str1[6],&tempRect,DT_LEFT|DT_TOP|DT_SINGLELINE);
pDC->SelectObject (oldfont);
//以上为显示文字
//以下为显示图片
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL, pForm->GetCapPath()+"pic1.bmp", IMAGE_BITMAP,
0, 0, LR_CREATEDIBSECTION |LR_DEFAULTSIZE | LR_LOADFROMFILE);
//原作者在显示图片时,用的函数为LoadBitmap(),这个函数的功能有限,而且必须将图片加载到mfc中的位图中,对于想要动态显示图片的话,很不方便,所我采用了 LoadImage()函数
BITMAPbitmap;
::GetObject(hBitmap,sizeof(BITMAP),&bitmap);
doubledScale=(double)m_cxWidth/bitmap.bmWidth;
int nScaledWidth=m_cxWidth/2;
intnScaledHeight=(int)(bitmap.bmHeight*dScale)/2;
HDC dcMem;
dcMem=::CreateCompatibleDC(pDC->m_hDC);
HBITMAPhOldBmp=(HBITMAP)::SelectObject(dcMem,hBitmap);
int nVertCenterPos =pDC->GetDeviceCaps (VERTRES) / 2;
::StretchBlt(pDC->m_hDC,DrawRect.left+100,nHeight/3,nScaledWidth,nScaledHeight,dcMem,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
::StretchBlt(pDC->m_hDC,nWidth/2+100,nHeight/3,nScaledWidth,nScaledHeight,dcMem,0,0,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
//StretchBlt的第二个和第三个参数可以调整图片的位置,第四个和第五个参数可以调整图片的大小
::SelectObject(dcMem,hOldBmp);
::DeleteDC(dcMem);
::DeleteObject(hBitmap);
return TRUE;
}
做完这些,就可以完成打印了,不过存在一个问题还没有测试,就是在本机上设计好的格式,在其它机器上是否会打乱,我还不知道,有待于验证。