在.net环境下开发MIS(管理信息系统)时,最终的结果往往需要通过打印机将数据打印出来。有时我们希望能够随心所欲地打印,这就需要针对自己的 系统开发适用的打印模块。事实上,.net框架提供了强大的打印支持,无论是用VB.net还是C#,都能写出自己满意的打印代码。本文将以VB.net 作为示例代码,介绍如何开发打印模块,重点是如何对打印的纸张页面进行设置,包括这样几个方面的问题:纸张类型、页边距、打印方向。
一、实现原理
FrameWork中有关打印的类都放在System.Drawing.Printing 命名空间中,因此我们必须要声明这个空间:Imports System.Drawing.Printing,C#中用Using关键字,这样就可以利用里面的类来编写自己的打印代码。
首先需要创建一个PrintDocument类的新实例,Private WithEvents pap As New PrintDocument,我们可以这样理解:pap是一张可以重复利用的纸张对象,将需要打印的内容放到该纸张上,然后调用 Print 方法来实际打印文档。
二、利用PageSetupDialog对话框设置页面
PageSetupDialog类表示一个对话框,它允许用户设置纸张类型、页边距和打印方向等属性,类似于Office中的“页面设置”对话框,如图所示。
要打开PageSetupDialog对话框,首先要定义一个PageSetupDialog类的实例:
Private psd As New PageSetupDialog,这里psd就是对话框的实例。利用PageSetupDialog对话框,用户可以自由地设置纸张的类型和页边距,还可 以设置打印的方向是纵向打印还是横向打印。并且利用PageSetupDialog对话框对页面的设置,实现起来也非常容易,只需要在页面设置的模块内加 入几句代码:
Private psd As New PageSetupDialog
With psd
.Document = pap
'对话框要设置的对象是上面定义的PrintDocumnet类的实例pap,也就是我们要打印的纸张对象
.PageSettings = pap.DefaultPageSettings
'将pap对象原先的页面信息赋值到psd对话框对象中
End With
If psd.ShowDialog = DialogResult.OK Then
pap.DefaultPageSettings = psd.PageSettings
End If
Psd.ShowDialog的作用就是打开页面设置对话框,在对话框中按下“确定”按钮,将返回一个DialogResult.OK的枚举 值,如果按下的是“取消”按钮,返回的枚举值将是DialogResult.Cancel。上面代码段的作用是:当打开页面设置对话框,对页面进行设置且 按下“确定”按钮后,将对话框中所设置的页面信息赋值到pap对象的DefaultPageSettings属性中,包括纸张的类型、纸张宽度和高度、页 边距大小、打印方向等信息,当然如果按下的是“取消”按钮,则不修改任何信息。
三、公制与英制单位的换算问题
利用PageSetupDialog对话框设置纸张的类型、页边距等信息后,再次进入页面设置的对话框,发现里面的页边距全部改变了,再进入又改变了,这是为什么呢?
其实原因很简单,单位的不同造成了这个现象。我们可以再看看上图中“页边距”一项明确的注明了单位采用的是“毫米”,说明在页面设置对话框中使用的是 公制长度计量单位,而在.net中采用的是英制的计量单位。英制中长度的基本计量单位是英寸,公制中长度的基本计量单位是厘米,打印时默认的长度单位为 1/100英寸。因此假设我们在页面设置对话框中设置上部边距为10mm,但.net把它转换成了英制单位,数值是1/2.54 * 100=39个1/100英寸,(1英寸约等于2.54厘米,1厘米=10毫米)所以,这时上部页边距的数值变成了39,当你再次打开页面设置对话框时, 系统将认为上部页边距是39个1/100厘米,也就是3.9毫米,按下“确定”按钮后,.net将再次对页边距进行转换,这时上部边距就约为15个 1/100英寸,这样结果当然与我们设置的相差甚远。
知道了原因,解决问题就很好办了。其实微软也考虑到了这个问题,提供了一个用于单位转换的类PrinterUnitConvert,如下所示:
If (System.Globalization.RegionInfo.CurrentRegion.IsMetric) Then
'如果使用的是公制单位
'将英制单位的数据转换成公制单位的数据
psd.PageSettings.Margins = PrinterUnitConvert.Convert (psd.PageSettings.Margins,PrinterUnit.Display,PrinterUnit.TenthsOfAMillimeter)
End If
pap.DefaultPageSettings = psd.PageSettings
Margins属性中保存的页面的上(Top)、下(Bottom)、左(Left)、右(Right)的页边距数值,利用 PrinterUnitConvert的Convert方法都可以转换,在上例中,PrinterUnit.Display是指1/100英寸的单位, PrinterUnit.TenthsOfAMillimeter是指1/100毫米的单位,这样就可以将英制单位转换为公制单位。
当然我们也可以自己编写代码进行转换,但请注意,转换时英制的单位是1/100英寸,转换后要以毫米为单位。
注意:转换时只须对纸张的页边距进行转换,纸张本身的宽度和高度在你选择一种纸张类型的时候,它已经自动帮你转换成英制单位了,千万不要画蛇添足。 以上我们介绍了如何利用PageSetupDialog对话框设置页面、公制与英制单位的换算,已经为打印程序的编写建立了一个良好的基础。接下来,我们就来介绍如何实现具体的特殊打印功能。
四、横向打印问题
如果在“页面设置”对话框中设置了横向打印,那么 pap.DefaultPageSettings.Landscape属性值将为True,这时需要考虑的是纸张的宽度和高度,一般情况下,大家习惯使用 pap.DefaultPageSettings.PaperSize属性来获取纸张的宽度和高度,PaperSize.Width表示宽度, PaperSize.Height表示高度,但是请注意:Paper Size属性是不考虑纸张的打印方向的,尽管你设置打印方向为横向,Paperize中的宽度和高度仍然是纵向的,因此,如果打印中可能会涉及到横向打印 的时候,我们尽量使用DefaultPageSettings.Bounds属性,.Bounds.Width表示纸张宽度,. Bounds.Height表示高度,重要的是,它们是考虑了打印方向后的纸张宽度和高度,那么在本例中,要获取纸张宽度可以用 pap.DefaultPageSettings.Bounds.Width,高度也一样。
当然,如果你非要用PaperSize属性表示纸张宽度和高度。可以定义一个结构来保存PaperSize中的宽度和高度,然后通过修改结构中变量的数值来改变宽度和高度。
Private Structure PrintArea
Dim AreaWidth As Integer ‘保存纸张的宽度
Dim AreaHeight As Integer ‘保存纸张的高度
End Structure
Public sctPageSizeArea as New PrintArea ‘定义一个PrintAr
ea结构的实例
sctpagesizeArea.AreaWidth=pap.DefaultPageSettings.PaperSize.Width
sctpagesizeArea.AreaHeight=pap.DefaultPageSettings.PaperSize.height
这样,我们用sctPageSizeArea.AreadWidth表示纸张宽度,用sctPageSizeArea.AreaHeight表示纸张高度,利用如下代码就可以对纸张的宽度和高度进行调整:
If pap.DefaultPageSettings.Landscape Then
'如果是横向打印,交换打印区域的宽度和高度
Dim ls As Int32
ls = sctPageSizeArea.AreaWidth
sctPageSizeArea.AreaWidth = sctPageSizeArea.AreaHeigh
sctPageSizeArea.AreaHeigh = ls
End If
利用“页面设置”对话框对页面进行设置虽然方便、简单,但它也存在自身的弱点:
1.每次打印都需要用户的干预。如果一个文档经常打印,而格式是固定的,这就显得很麻烦;
2.页面设置对话框中可供选择的纸张类型非常少,经常不符合我们的打印要求;
3.页面设置对话框中没有提供自定义纸张大小的功能,不能满足我们的特殊要求。
基于以上原因,我们在有些时候必须绕开页面设置对话框,对纸张类型直接进行设置。
.net默认的纸张类型为A4,我们可以直接将纸 张设置为一个已知或自定义的纸张类型,如A3等,再直接通过打印或打印预览方法将结果输出,这样就不必通过页面设置对话框。下面我们来自定义一个16开 (16开在Office的页面设置对话框中存在,但在.net的页面设置对话框中不支持)的纸张类型,演示如何设置一个自定义的页面。
Dim ps As New PageSettings '定义一个页面设置类的实例
Dim myPaperSize As PaperSize ‘定义一个纸张类型的实例
For Each myPaperSize In ps.PrinterSettings.PaperSizes
'循环遍历当前打印机中所有支持的纸张类型
If myPaperSize.Kind = PaperKind.16开 Then ‘是否有16开的纸张类型
Exit For ‘如果有16开的纸张类型,则退出循环
End If
Next
If myPaperSize.Kind <> PaperKind.16开 Then
'如果当前打印机不支持16开的纸张类型,那么自定义16开的纸张类型
'当前打印机有16开的纸张类型,那么就使用系统定义的16开纸张类型
myPaperSize = New System.Drawing.Printing.PaperSize("16开",724,1024)
End If
ps.PaperSize = myPaperSize '设置为指定的纸张类型
ps.Landscape = False '打印方向为纵向
Ps.Margins.Top = 50 ‘设置顶部页边距
Ps.Margins.Left = 50 ‘设置左部页边距
pap.DefaultPageSettings = ps ‘当前打印页面为上面设置的打印页面
在设置纸张的大小时,特别要注意,一定要使用英制单位,也就是以1/100英寸作为宽度和高度的单位,如16开纸张的宽度是18.4cm,那么就要转换成1/100英寸,18.4/2.54*100后取整数,得到724,在设置高度和页边距大小时都需要这样转换。
编后:通过本文,大家可以看出,编写打印程序并不是调用系统函数那么简单,掌握文中技巧,才能真正随心所欲地操纵打印页面。
转自:http://hi.baidu.com/gengxiaoguo/blog/item/2cb307de039ae25c95ee3765.html
原文链接:https://www.f2er.com/vb/262582.html