【转】掌握.NET中的日常打印

     你可以用几种方法在.NET中编程来生成打印输出结果(如报表)。对Windows程 序员来说,Visual Studio提供的Crystal Reports 实际上是人们常用的打印报表的工具,但对不太复杂的报表来说,这个工具就有些大材小用了。当然,你可以用很好的Win32 API调用,但是尽管API可以让你有完 全的控制权,它同时也把你锁定到一个单一的平台上了。如果Microsoft或另外的公司(如拥有Mono项目的Ximian公司)把Framework转移到另外的平台上,那么运用API的 程序仍会锁定在Windows上,除非你为新的平台重新编写它们。

    .NET Framework可以让你以一种新的方式来使用这些打印方法,System.Drawing.Printing名字空间的类将Win32 API的细粒度控制(fine-grain control)与相对简单的Visual Basic传统的Printer对象结 合了起来(见表下)。

    fine-grain control
)与相对简单的Visual Basic传统的Printer对象结合 了起来(见表下)。

说明

PrintDocument

可以 让你定义一个对象,该对象把输出发送到一台打印机。

PrintEventArgs

BeginPrintEndPrint事件提供所有的必需的信 息。

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

指定 一个文件是如何打印的,包括文件在哪个打印机上打印。它 是与特定的PrintDocument相应的。

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 pageto 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对象(见下)。

 图1.

作为 选择,你也可以把所有的打印功能封装到PrintDocument派生的一个单独的类中, 然后重载触发相应事件的方法。你可以用你自定义的类,而不用实例化一个PrintDocument对象(见列下)。这是 一个很好的方法,但是为了保持一致,使代码清晰,我将继续讲述事件绑定方法。

C#:继承 PrintDocument

列表 2.

PrintDocument派生一个新类,这样你就可以把所有打印功能封装在一个单独的地方,从而提高代码的重用性。

public class CustomPrintDocument : PrintDocument {

   private StreamReader dataToPrint;

   public CustomPrintDocument(StreamReader data) :      

   base()

   {

      dataToPrint = data;

   }

   protected override void      

      OnBeginPrint(PrintEventArgs

      ev) {

      base.OnBeginPrint(ev) ;

   }

   protected override void

      OnEndPrint(PrintEventArgs ev)

   {

      base.OnEndPrint(ev);

   }

   protected override void

      OnQueryPageSettings

      (QueryPageSettingsEventArgs ev)

   {

      base.OnQueryPageSettings(ev);

   }

   protected override void

      OnPrintPage(PrintPageEventArgs

      ev) {

      base.OnPrintPage(ev);

      ev.Graphics.DrawString("this is a test", new

         Font("Arial", 24), Brushes.Black, 100,

         100);

      ev.HasMorePages = false;

   }

}

 

    PrintDocument类没有制图工具,所以创建报表需要花些时间――但这是值得的。创建一个新的报表的最好的方法是用一张空白的 纸。在了解了报表的目的后,你就可以在纸上通过画方框来代表不同的区域进行设计了,如页眉、正文和页脚(见下)。

 


1. 显示你的报表
   
在定义了你的 Rectangle 对象后,你只需要用 DrawRectangle 方法写一行代码,用你选择的画笔在屏幕上画一个长方形边框就 行了。


   

然后花些时间详细编写每个区域的数据将来自哪里,以及各个数据将放置在什么位置。可以说这个时候是你确保最终用户所看到的页面与你设计 的页面是否是一致的最佳时刻。用户对报表比对应用程序的任何部分的挑剔都要多,所以你应该尽可能多花些时间来设计它。一旦你花了很多时间来设计报表并对它的打印结果了如指掌后,那么写代码

 

 原文URL:http://www.builder.com.cn/2007/0930/530417.shtml

 

转载于:https://www.cnblogs.com/jeriffe/articles/1689783.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值