12.2 打 印 输 出
视频讲解:光盘/TM/Video/12/打印输出.exe
打印在许多的应用程序中都使用,本节将介绍如何获得打印机设备上下文,以及打印文本信息和图像数据。
12.2.1 获取打印机设备上下文
虽然在MFC中大大简化了打印工作,并提供了相关的打印机制。但是,在基于对话框的应用程序中进行打印时,想要调用MFC的打印机制就比较麻烦,这时就需要程序员自己来编写打印功能。在进行打印编程之前,首先要获得打印机的设备上下文,如果已经知道打印机的设备名称,可以通过CDC类的CreateDC方法来创建打印机的设备上下文。
CDC tempdc;
tempdc.CreateDC("", "HP LaserJet 1020", "", "");
在上面的代码中使用CreateDC方法创建打印机设备上下文,CreateDC方法的语法如下:
virtual BOOL CreateDC( LPCTSTR lpszDriverName, LPCTSTR lpszDeviceName, LPCTSTR lpszOutput, const void* lpInitData );
CreateDC语法中的参数说明如表12.2所示。
表12.2 CreateDC语法中的参数说明
参 数 | 描 述 |
lpszDriverName | 指向非NULL的字符串的指针,字符串为设备驱动程序的不带扩展名的文件名,也可以使用CString对象传递参数 |
lpszDeviceName | 指向非NULL的字符串的指针,字符串为支持特定设备的文件名。如果模块不仅仅支持一个设备,也可以使用CString对象传递参数 |
lpszOutput | 指向非NULL的字符串的指针,字符串是指定了物理输出介质的文件和设备名(文件或输出端口),也可以使用CString对象传递参数 |
lpInitData | 指向DEVMODE结构的指针,该结构包含指定设备驱动程序的初始数据,Windows的DocumentProperties函数从该结构中获得指定设备的信息,如果设备驱动程序使用用户在控制面板中设定了默认值,lpInitData参数一定要设置为NULL |
如果想要使用打印设备而不知道设备名称时,可以调用打印对话框使用户选择打印机,然后使用CPrintDialog类的GetPrinterDC方法来获得设备上下文。
DWORD dwflags = PD_PAGENUMS|PD_HIDEPRINTTOFILE|PD_SELECTION; //设置打印对话框风格
CPrintDialog dlg(false,dwflags,NULL); //创建打印对话框
if (dlg.DoModal()==IDOK) //是否按下“打印”按钮
{
CDC dc; //声明设备上下文
dc.Attach(dlg.GetPrinterDC()); //获取打印机DC
}
在上面的代码中先通过CPrintDialog类构造打印对话框,然后调用DoModal方法显示打印对话框,最后通过GetPrinterDC方法获得用户选择的打印机设备上下文。
如果不想选择打印机,也可以使应用程序调用当前机器默认的打印机,可以通过CPrintDialog类的GetDefaults方法和GetPrinterDC方法来实现,或者在构造打印对话框时设置其具有 PD_ RETURNDEFAULT风格。
DWORD dwflags = PD_PAGENUMS|PD_HIDEPRINTTOFILE| PD_RETURNDEFAULT; //设置打印对话框风格
CPrintDialog dlg(false,dwflags,NULL); //创建打印对话框
dlg.GetDefaults(); //获取设备默认项
dlg.GetPrinterDC(); //获取打印机DC
在上面的代码中先通过CPrintDialog类构造打印对话框,然后调用GetDefaults方法获取默认打印设备,最后通过GetPrinterDC方法获得默认打印机的设备上下文。
12.2.2 打印文本信息
在设计一些应用程序的打印功能时,文本信息的打印是必不可少的。下面将设计一个打印文本信息的程序。具体步骤如下:
例12.1 打印文本信息。(实例位置:光盘/TM/Instances/12/例12.1)
(1)创建一个基于对话框的工程,工程名称为PrintText。向对话框中添加按钮控件。
(2)在对话框类的头文件中定义变量。
CString str[7]; //打印的字符串数组
int screenx,screeny; //窗口每英寸像素数
int printx,printy; //打印机每英寸像素数
double ratex,ratey; //打印机与屏幕的像素比率
CFont font; //打印文本的字体
(3)在对话框初始化(OnInitDialog方法中)时设置打印文本。
BOOL CPrintTextDlg::OnInitDialog()
{
//设置打印文本
str[0] = "花间一壶酒,独酌无相亲。/r/n";
str[1] = "举杯邀明月,对影成三人。/r/n";
str[2] = "月既不解饮,影徒随我身。/r/n";
str[3] = "暂伴月将影,行乐须及春。/r/n";
str[4] = "我歌月徘徊,我舞影凌乱。/r/n";
str[5] = "醒时同交欢,醉后各分散。/r/n";
str[6] = "永结无情游,相期渺云汉。/r/n";
return TRUE;
}
(4)在OnCtlColor消息处理函数中绘制对话框背景颜色。
HBRUSH CPrintTextDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);
CBrush m_brush (RGB(255,255,255)); //创建画刷
CRect m_rect;
GetClientRect(m_rect); //获得客户区域
pDC->SelectObject(&m_brush); //选入画刷
pDC->FillRect(m_rect,&m_brush); //填充背景
return m_brush;
}
(5)添加自定义函数DrawText,根据参数判断是在屏幕绘制还是在打印纸绘制。
void CPrintTextDlg::DrawText(CDC *pDC, BOOL IsPrint)
{
if (!IsPrint) //预览
{
ratex = ratey = 1; //当预览时设置比率为1
}
else //判断是打印
{
printx = pDC->GetDeviceCaps(LOGPIXELSX);
printy = pDC->GetDeviceCaps(LOGPIXELSY);
ratex = (double)(printx)/screenx;
ratey = (double)(printy)/screeny;
pDC->StartDoc("printtext"); //开始打印
}
font.CreatePointFont(120,"宋体",pDC); //创建字体
for (int i=0;i<7;i++) //设置循环
{
pDC->SelectObject(&font); //将字体选入设备上下文
pDC->TextOut(int(100*ratex),int(50+i*30*ratey),str[i]); //打印文本
}
if (IsPrint) //判断是打印
{
pDC->EndDoc(); //结束打印
}
font.DeleteObject(); //释放字体
}
(6)在OnPaint方法中调用DrawText函数将文本绘制到对话框中。
void CPrintTextDlg::OnPaint()
{
//……系统代码省略
CDC* pDC = GetDC(); //获得设备上下文
//获得屏幕每英寸像素数
screenx = pDC->GetDeviceCaps(LOGPIXELSX);
screeny = pDC->GetDeviceCaps(LOGPIXELSY);
DrawText(pDC,FALSE);
}
(7)处理“打印”按钮的单击事件,获取打印机设备上下文,并将文本内容绘制到打印纸上。
void CPrintTextDlg::OnButprint()
{
DWORD dwflags = PD_PAGENUMS|PD_HIDEPRINTTOFILE|PD_SELECTION; //设置打印对话框风格
CPrintDialog dlg(false,dwflags,NULL); //创建打印对话框
if (dlg.DoModal() == IDOK) //是否按下“打印”按钮
{
CDC dc; //声明设备上下文
dc.Attach(dlg.GetPrinterDC()); //获取打印机DC
int leftmargin;
leftmargin = dc.GetDeviceCaps(PHYSICALOFFSETX); //获得左边界
CRect m_rect(-leftmargin,0,dc.GetDeviceCaps(PHYSICALWIDTH)-leftmargin
,dc.GetDeviceCaps(PHYSICALHEIGHT)); //打印纸区域
DrawText(&dc,TRUE);
}
}
(8)运行程序,效果如图12.1所示。
图12.1 打印文本信息
12.2.3 打印图像
随着多媒体技术的发展,图片处理设备也得到了广泛的发展,而且网络的普及也使图片处理成为人们使用计算机的日常操作。因此,图片的浏览和打印已经成为人们的重要需求之一。下面通过一个实例介绍如何打印图像。
例12.2 设置列表视图背景位图。(实例位置:光盘/TM/Instances/12/例12.2)
(1)创建一个基于对话框的工程,工程名称为PrintImage。向对话框资源窗口中添加图片控件和按钮控件,并添加一个位图资源,设置图片控件的属性,如图12.2所示。
图12.2 图片控件的属性设计
(2)为图片控件添加一个成员变量m_Image。
(3)处理“打印”按钮的单击事件,在该事件的处理函数中设置打印图像功能。
void CPrintImageDlg::OnButprint()
{
CRect m_rect;
//获取图像的大小
m_Image.GetClientRect(m_rect);
CDC* pImageDC = m_Image.GetDC(); //获得控件画布
int formx,formy;
//获得屏幕分辨率
formx = pImageDC->GetDeviceCaps(LOGPIXELSX);
formy = pImageDC->GetDeviceCaps(LOGPIXELSY);
ReleaseDC(pImageDC);
CPrintDialog m_printdlg(FALSE,PD_RETURNDEFAULT); //构造打印对话框
if (m_printdlg.DoModal() == IDOK)
{
CDC pdc;
pdc.Attach(m_printdlg.GetPrinterDC());
//获取打印机与屏幕的分辨率比率
int printerx,printery;
printerx = pdc.GetDeviceCaps(LOGPIXELSX);
printery = pdc.GetDeviceCaps(LOGPIXELSY);
double ratex,ratey;
ratex = (double)printerx/formx;
ratey = (double)printery/formy;
CClientDC dc(this);
CBitmap bmp;
bmp.CreateCompatibleBitmap(&dc,m_rect.Width(),m_rect.Height()); //创建位图
CDC imagedc;
imagedc.CreateCompatibleDC(&dc); //创建兼容的画布
imagedc.SelectObject(&bmp); //选入位图
imagedc.BitBlt(0,0,m_rect.Width(),m_rect.Height(),&dc,0,0,SRCCOPY); //绘制位图
//打印图像
pdc.StartDoc("printimage");
pdc.StretchBlt(0,0,(int)(m_rect.Width()*ratex),(int)(m_rect.Height()*
ratey),&imagedc,0,0,m_rect.Width(),m_rect.Height(),SRCCOPY);
pdc.EndDoc();
}
}