分享
 
 
 

掌握.NET中的日常打印

王朝c#·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

你可以用几种方法在.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

为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

指定一个文件是如何打印的,包括文件在哪个打印机上打印。它是与特定的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 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派生一个新类,这样你就可以把所有打印功能封装在一个单独的地方,从而提高代码的重用性。

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方法写一行代码,用你选择的画笔在屏幕上画一个长方形边框就行了。

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

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有