.NET Framework可以让你以一种新的方式来使用这些打印方法,System.Drawing.Printing名字空间的类将Win32 API的细粒度控制(fine-grain control)与相对简单的Visual Basic传统的Printer对象结 合了起来(见表下)。
fine-grain control)与相对简单的Visual Basic传统的Printer对象结合 了起来(见表下)。
类 | 说明 |
PrintDocument | 可以 让你定义一个对象,该对象把输出发送到一台打印机。 |
PrintEventArgs | 为BeginPrint和EndPrint事件提供所有的必需的信 息。 |
PrintPageEventArgs | 为PrintPage事件提供所有必需的信息。 |
QueryPageSettingsEventArgs | 为QueryPageSettings事件提供信息。 |
PrintController | 控制 一个PrintDocument是如何打印的。 |
StandardPrintController | 派生 于PrintController。 |
PreviewPrintController | 派生 于PrintController。 |
PreviewPageInfo | PreviewPrintController 经常运用这个类。它为一个单独的页面指定了预览信息。 |
PageSettings | 指定 一个单独的打印页面的设置。 |
Margins | 可以 让你指定一个打印页面的页边距。页面的顶部、左边、右边和底部边距属性是以英寸(×100)的形式返回的。 |
MarginsConverter | 可以 让你把一个Margins对象转换成另外的类型,把另外的类型转换成一个Margins对象。 |
PaperSize | 指定 一页纸的大小。当同一个PageSettings对象一起使用时,它指的 是一个页面的纸张大小。当用于PrinterSettings时,它可以让你得到打印 机上可以用的纸张大小。 |
PaperSizeCollection | PaperSize对象的一个集合。 |
PaperSource | 像PaperSize类一样, PaperSource 是由一个PageSettings对象和一个PrinterSettings对象使用的。当用于PageSettings时,它可以让你为一个特定页面得到纸张来源。当用于PrinterSettings时,它可以让你得到打印机运用的所有纸张来源。 |
PaperSourceCollection | PaperSource 对象的一个集合。 |
PrinterSettings | |
PrinterResolution | 可以 让你得到横向的和纵向的DPI,以及实际的打印机分辨率(draft, high, low, 等等)。 |
PrinterResolutionCollection | PrinterResolution 对象的一个集合。 |
InvalidPrinterException | 表示 将抛出的异常(如果你用无效的设置来访问一台打印机)。 |
PrintingPermission | 控制 对打印机的使用权限。 |
PrintingPermissionAttribute | 允许 检测打印权限。 |
表 1 研 究 .NET的众多的打印类.
运用.NET Framework的System.Drawing.Printing名 字空间,你就可以程序化 地处理许多打印任务,该名字空间包含20多个类、7个 枚举类型和3个委托类型(delegate)。 让我们来看看对每个类的简要说明吧!
在此,我将重点讲述该名字空间的主要的类,它们可以让你创建复杂程度适度的报表。PrintDocument类 是这些类中最重要的。它可以让你定义一个对象,该对象发送输出结果到一个目的地,可以是一台打印机,或者是显示一个打印预览(运用PrintPreviewDialog类)。我还会讲述PrinterSettings类, 它可以让你控制文件是如何打印的。
你可以很容易地在C#中创建一个PrintDocument对 象,并把它附到一个事件处理程序上 (实际处理打印的代码):
PrintDocument doc = new PrintDocument(); doc.PrintPage += new PrintPageEventHandler( doc_PrintPage); |
PrintPage事件处理程序有 一个PrintPageEventArgs类型的参数。这个参数包含与该事件相关的数据,包括当前 页面的页面设置、页边距信息以及是否有更多的页需要打印。每个页面触发该事件一次,直到ev.HasMorePages等 于false:
private void doc_PrintPage(object sender, PrintPageEventArgs ev) |
将Graphics用于Fonts和Fills
ev参数引用了你用来输出数据的Graphics制 图区。Graphics有用来打印图象、文本、形状和线条的方法。你可以用DrawString方法来定义你要用的font(字 体)和brush(画刷)。一个brush定 义了一个图形的内部是如何填充的。你也需要告诉DrawString方法你想在哪里打印文本。PrintPageEventArgs类有一个读写属性――HasMorePages――它 指明是否需要打印更多的页面:
Font f = new Font("Arial", 12); ev.Graphics.Drawstring("Hello, World.", f, Brushes.Black, 100, 100); ev.HasMorePages = false; |
现在,你已经创建了一个PrintDocument对象并把它和一个事件处理程序联系起来了。你已经给事件处理程序中添加了代码,来打印一个单独的字符串,它的位置是距页面左边一英寸、距页面顶部一英寸,用的是12磅、 Arial的字体。现在我们来打印文件:
doc.Print(); |
在缺省设置下,PrintDocument类的Print方法在缺省打印机上打印结果,除非你另外指定。你可以用PrintDialog类 来另外指定,它是System.Windows.Forms.CommonDialog名字空间的 一部分。PrintDialog可以让你选择打印机,选择打印文件的哪部分,选择打印份数,来随意地打印一个文件。
PrintDialog类的PrinterSettings属性可以 让你将诸如copies、from page和to page的属性放置到一个特定文件的PrinterSettings对 象中。换句话说,单独的PrintDocument对象有一个PrinterSettings对象,它指定打印的份数、打印的范围、要运用的打印机的名字以及关于打印机本身 的信息。
IPrinterSettings类中的一个bug会导致Copies属性总是返回一个为1的值,而不管你在PrintDialog中输入了多少份数。然而,PrintDocument.Print()方 法仍然打印正确的份数,所以只有当你想将这个值用于其它地方时,才显示这个bug。当你执行Print方法时,系统运 用这些设置。你可以提供一个实际的PrinterSettings对象或提供一个Document对象:
PrintDialog pd = new PrintDialog(); pd.Document = doc; pd.ShowDialog(); |
然后,运用CommonDialog名字空间的PageSetupDialog,你可以指定纸张大小、纸张来源、打印方向和页边距。PageSetupDialog和PrintDialog都 需要你提供一个Document对象或一个PageSettings对 象。PageSettings对象适用于一个单独的打印页面,可以处理页边距、纸张大小以及是否用 颜色打印页面:
PageSetupDialog ps = new PageSetupDialog(); ps.Document = doc; ps.ShowDialog(); |
打印一个文件
当然,许多应用程序打 印存储在一个文件或某种数据库中的信息,所以现在我将讲述一个更复杂的例子:打印一个以逗号分 隔的联系清单文本文件。你可以将一个数据集、甚至一个XML文件中数据所运用的方法用在这里。本例的数据来自Northwind数据库的Customers表, 格式如下:
Name, Title, Phone, Fax |
通过在类的级别声明一个StreamReader对象,然后将一个文件分配给它,你就可以从一个文本文件打印该例子了。打开文件,修改PrintPage事 件处理程序来 打印文件的每一行,按需要格式化数据。
PrintDocument类有好几个事件。你已经用了PrintPage事 件了;现在我们来添加更多的事件。当开始一个打印任务时(在实际打印任何东西前),触发BeginPrint事 件。相应的事件是EndPrint,该事件是在所有页面结束打印时触发的。创建PrintPage事件需要的任何对象,或在BeginPrint中 打开任何数据源,然后在EndPrint中关闭或释放(deallocate) 它们。不要忘记将这些事件绑定到PrintDocument对象(见下)。
作为 选择,你也可以把所有的打印功能封装到PrintDocument派生的一个单独的类中, 然后重载触发相应事件的方法。你可以用你自定义的类,而不用实例化一个PrintDocument对象(见列下)。这是 一个很好的方法,但是为了保持一致,使代码清晰,我将继续讲述事件绑定方法。
C#:继承 PrintDocument 列表 2. 从PrintDocument派生一个新类,这样你就可以把所有打印功能封装在一个单独的地方,从而提高代码的重用性。
|
PrintDocument类没有制图工具,所以创建报表需要花些时间――但这是值得的。创建一个新的报表的最好的方法是用一张空白的 纸。在了解了报表的目的后,你就可以在纸上通过画方框来代表不同的区域进行设计了,如页眉、正文和页脚(见下)。
在定义了你的 Rectangle 对象后,你只需要用 DrawRectangle 方法写一行代码,用你选择的画笔在屏幕上画一个长方形边框就 行了。
然后花些时间详细编写每个区域的数据将来自哪里,以及各个数据将放置在什么位置。可以说这个时候是你确保最终用户所看到的页面与你设计 的页面是否是一致的最佳时刻。用户对报表比对应用程序的任何部分的挑剔都要多,所以你应该尽可能多花些时间来设计它。一旦你花了很多时间来设计报表并对它的打印结果了如指掌后,那么写代码
原文URL:http://www.builder.com.cn/2007/0930/530417.shtml