12.3 打 印 控 制
视频讲解:光盘/TM/Video/12/打印控制.exe
编写打印程序之所以复杂,在于其处理的信息比较复杂,所以要想编写一个好的打印程序,掌握打印相关的控制技术是必不可少的。DEVMODE结构用于对打印进行一些基本设置,其语法如下:
typedef struct _devicemode {
BCHAR dmDeviceName[CCHDEVICENAME];
WORD dmSpecVersion;
WORD dmDriverVersion;
WORD dmSize;
WORD dmDriverExtra;
DWORD dmFields;
union {
struct {
short dmOrientation;
short dmPaperSize;
short dmPaperLength;
short dmPaperWidth;
};
POINTL dmPosition;
};
short dmScale;
short dmCopies;
short dmDefaultSource;
short dmPrintQuality;
short dmColor;
short dmDuplex;
short dmYResolution;
short dmTTOption;
short dmCollate;
BCHAR dmFormName[CCHFORMNAME];
WORD dmLogPixels;
DWORD dmBitsPerPel;
DWORD dmPelsWidth;
DWORD dmPelsHeight;
DWORD dmDisplayFlags;
DWORD dmDisplayFrequency;
#if(WINVER >= 0x0400)
DWORD dmICMMethod;
DWORD dmICMIntent;
DWORD dmMediaType;
DWORD dmDitherType;
DWORD dmReserved1;
DWORD dmReserved2;
#if (WINVER >= 0x0500) || (_WIN32_WINNT >= 0x0400)
DWORD dmPanningWidth;
DWORD dmPanningHeight;
#endif
#endif /* WINVER >= 0x0400 */
} DEVMODE;
DEVMODE结构成员说明如表12.3所示。
表12.3 DEVMODE结构成员说明
成 员 |
描 述 |
dmDeviceName |
指定了驱动程序支持的设备名称 |
dmSpecVersion |
指定了初始化数据的版本数字 |
dmDriverVersion |
指定了打印机驱动程序开发商分配的打印机驱动程序版本号 |
dmSize |
指定了DEVMODE结构的大小,以字节为单位,不包括dmDriverData(与设备有关)成员 |
dmDriverExtra |
包含了这个结构后面的私有驱动程序数据的数目,以字节为单位。如果设备驱动程序不使用该设备独有的信息,就把这个成员设为零 |
dmFields |
指定了DEVMODE结构的其余成员中哪些已被初始化 |
dmOrientation |
选择纸的方向 |
dmPaperSize |
选择将用于打印的纸张大小 |
dmPaperLength |
重定义由dmPaperSize成员指定的纸张长度,可用于自定义纸张大小,也可以用于点阵打印机,这种打印机能打出任意长度的纸张。这些值与这个结构中其他指定物理长度的值都是以0.1毫米为单位的 |
dmPaperWidth |
重载由dmPaperSize成员指定的纸张宽度 |
dmScale |
指定了打印输出的缩放因子。实际的页面大小为物理纸张的大小乘以dmScale/100 |
dmCopies |
如果设备支持多页拷贝,则选择了要打印的拷贝数目 |
dmDefaultSource |
保留,必须为0 |
dmPrintQuality |
指定了打印机的分辨率 |
dmColor |
对于彩色打印机,在彩色和单色之间切换 |
dmDuplex |
为支持双面打印的打印机选择双面打印方式 |
dmYResolution |
指定了打印机在y方向的分辨率,以每英寸的点数为单位。如果打印机对该成员进行了初始化,dmPrintQuality成员指定了打印机在x方向的分辨率,以每英寸点数为单位 |
dmTTOption |
指明如何打印TrueType字体 |
dmCollate |
指定在打印多份拷贝时是否使用校对。使用DMCOLLATE_FALSE后能够得到更快更有效的输出,因为不管要打印多少份拷贝,只向打印机传送一次数据,打印机仅被通知再打印一页 |
dmFormName |
指定了要使用的格式名字 |
dmUnusedPadding |
用于将结构对齐到DWORD边界。不能使用或引用这个成员。它的名字和用法是保留的,在以后的版本中可能会变化 |
dmBitsPerPel |
指定了显示设备的颜色分辨率,以像素的位数为单位 |
dmPelsWidth |
指定了可见设备表面的以像素为单位的宽度 |
dmPelsHeight |
指定了可见设备表面的以像素为单位的高度 |
dmDisplayFlags |
指定了设备的显示模式 |
dmDisplayFrequency |
指定了显示设备的特定模式所使用的以赫兹为单位的频率(每秒的周期数) |
12.3.1 控制打印方向
在开发具有打印功能的应用程序时,有时因为打印的数据太大导致正常打印时无法打印出完整的信息,要解决这个问题,可以在打印时设置横向打印,这样就可以增加水平方向的空间,不必为无法打印出完整信息而苦恼。
通过CPrintDialog类的GetDevMode方法可以获得DEVMODE结构,在该结构中包含了打印设备中的许多基本参数,其中dmOrientation参数指定了打印的方向,当dmOrientation参数值为DMORIENT_ LANDSCAPE时横向打印,值为DMORIENT_PORTRAIT时纵向打印。
下面通过一个实例介绍如何控制打印方向。
例12.3 控制打印方向。(实例位置:光盘/TM/Instances/12/例12.3)
(1)创建一个基于对话框的工程,工程名称为Orientation。向对话框资源窗口中添加两个按钮控件。
(2)在对话框的头文件中声明变量。
CString str[6]; //打印的字符串数组
int screenx,screeny; //窗口每英寸像素数
int printx,printy; //打印机每英寸像素数
double ratex,ratey; //打印机与屏幕的像素比率
CFont m_Font; //打印文本的字体
(3)添加Draw方法,用于绘制打印信息。
void COrientationDlg::Draw(CDC *pDC, BOOL isprinted)
{
m_Font.CreatePointFont(150,"宋体",pDC);
if (!isprinted) //预览
{
ratex = ratey = 1;
}
else //打印
{
//计算屏幕和打印机比率
printx = pDC->GetDeviceCaps(LOGPIXELSX);
printy = pDC->GetDeviceCaps(LOGPIXELSY);
ratex = (double)(printx)/screenx;
ratey = (double)(printy)/screeny;
pDC->StartDoc("print"); //开始打印
}
pDC->SelectObject(&m_Font);
for (int i=0;i<6;i++)
{
pDC->TextOut(int(100*ratex),int((30+i*40)*ratey),str[i]); //打印文本
}
if (isprinted)
{
pDC->EndDoc(); //结束打印
}
m_Font.DeleteObject();
}
(4)添加SetPrint方法,用于设置打印方向,并获取打印机设备上下文,调用Draw方法进行打印绘制。
void COrientationDlg::SetPrint(BOOL isway)
{
DWORD dwflags=PD_ALLPAGES | PD_NOPAGENUMS | PD_USEDEVMODECOPIES
| PD_SELECTION | PD_HIDEPRINTTOFILE | PD_RETURNDEFAULT;
CPrintDialog dlg(false,dwflags,NULL); //构造打印对话框
If (dlg.DoModal() == IDOK)
{
LPDEVMODE dv = dlg.GetDevMode();
//设置打印方向
if(isway)
dv->dmOrientation = DMORIENT_LANDSCAPE; //横向打印
else
dv->dmOrientation = DMORIENT_PORTRAIT; //纵向打印
CDC dc;
dc.Attach(dlg.GetPrinterDC());
dc.ResetDC(dv);
Draw(&dc,TRUE);
}
}
(5)处理“横向打印”和“纵向打印”按钮的单击事件,在这两个按钮的单击事件处理函数中调用SetPrint方法设置打印方向。
void COrientationDlg::OnButhorzres()
{
SetPrint(TRUE); //横向打印
}
void COrientationDlg::OnButverters()
{
SetPrint(FALSE); //纵向打印
}
(6)运行程序,效果如图12.4所示。
图12.4 控制打印方向
12.3.2 设置打印纸大小
Windows系统中提供了许多规格的打印纸,但实际应用中,这些规格的纸张并不能满足需求,因此,在设计程序时,需要自定义纸张的大小。下面通过实例介绍如何设置打印纸的大小。
例12.4 设置打印纸大小。(实例位置:光盘/TM/Instances/ 12/例12.4)
(1)创建一个基于对话框的工程,工程名称为SetPaper。向对话框资源窗口中添加静态文本、编辑框和按钮控件,如图12.5所示。
图12.5 对话框资源设计
(2)为编辑框添加两个整型变量m_Length和m_Width。
(3)处理“打印”按钮的单击事件,在该事件的处理函数中设置打印纸的大小,并打印数据。
void CSetPaperDlg::OnButprint()
{
UpdateData(TRUE);
DWORD dwflags=PD_ALLPAGES | PD_NOPAGENUMS | PD_USEDEVMODECOPIES
| PD_SELECTION | PD_HIDEPRINTTOFILE | PD_RETURNDEFAULT; //打印对话框风格
CPrintDialog dlg(FALSE,dwflags,NULL); //构造打印对话框
if (dlg.DoModal() == IDOK)
{
//定义打印纸的大小
LPDEVMODE dev = dlg.GetDevMode();
dev->dmPaperSize = DMPAPER_USER;
dev->dmPaperLength = m_Length * 10; //打印纸长度
dev->dmPaperWidth = m_Width * 10; //打印纸宽度
dev->dmFields = DM_PAPERSIZE | DM_PAPERWIDTH
| DM_PAPERLENGTH | dev->dmFields;
CDC dc;
dc.Attach(dlg.GetPrinterDC()); //获得打印机设备上下文
dc.ResetDC(dev);
CFont TextFont;
TextFont.CreatePointFont(150,"宋体",&dc); //设置字体
dc.StartDoc("print"); //开始打印
dc.SelectObject(&TextFont); //选入字体
dc.TextOut(200,200,"山无棱,江水为竭,冬雷震震,夏雨雪,天地合,乃敢与君绝!");
dc.EndDoc(); //结束打印
TextFont.DeleteObject();
dc.DeleteDC();
}
}
(4)运行程序,效果如图12.6所示。
图12.6 设置打印纸大小