PrintDocument组件是用于完成打印的类,其常用属性、方法和事件如下:
- 属性DocumentName:
字符串类型,记录打印文档时显示的文档名(例如,在打印状态对话框或打印机队列中显示)。
- 方法Print:
开始文档的打印。
- 事件BeginPrint:
在调用Print方法后,在打印文档的第一页之前发生。
- 事件PrintPage:
需要打印新的一页时发生。
- 事件EndPrint:
在文档的最后一页打印后发生。
打印步骤:
- 创建PrintDocument组件的对象。
- 使用页面设置对话框PageSetupDialog设置页面打印方式,这些设置作为要打印的所有页的默认设置。使用打印对话框PrintDialog设置对文档进行打印的打印机的参数。在打开两个对话框前,首先设置对话框的属性Document为指定的PrintDocument类对象,修改的设置将保存到PrintDocument组件对象中。
- 调用PrintDocument.Print方法来实际打印文档。当调用该方法后,引发下列事件:BeginPrint、PrintPage、EndPrint。其中每打印一页都引发PrintPage事件,打印多页,要多次引发PrintPage事件。完成一次打印,可以引发一个或多个PrintPage事件。
程序员应为这3个事件编写事件处理函数:
BeginPrint事件处理函数进行打印初始化,一般设置在打印时所有页的相同属性或共用的资源,例如所有页共同使用的字体、建立要打印的文件流等。
PrintPage事件处理函数负责打印一页数据。
EndPrint事件处理函数进行打印善后工作。
这些处理函数的第2个参数System.Drawing.Printing.PrintEventArgs e提供了一些附加信息,主要有:
e.Cancel:布尔变量,设置为true,将取消这次打印作业。
e.Graphics:所使用的打印机的设备环境。
e.HasMorePages:布尔变量。PrintPage事件处理函数打印一页后,仍有数据未打印,退出事件处理函数前设置HasMorePages=true,退出PrintPage事件处理函数后,将再次引发PrintPage事件,打印下一页。
e.MarginBounds:打印区域的大小,是Rectangle结构,元素包括左上角坐标:Left和Top,宽和高:Width和Height。单位为1/100英寸。
e.MarginBounds:打印纸的大小,是Rectangle结构。单位为1/100英寸。
e.PageSettings:PageSettings类对象,包含用对话框PageSetupDialog设置的页面打印方式的全部信息。可用帮助查看PageSettings类的属性。
下边为这3个事件编写事件处理函数,具体步骤如下:
-
在最后一个using语句之后增加语句:
using System.IO; using System.Drawing.Printing;
-
本例打印或预览RichTextBox中的内容,增加变量:
StringReader streamToPrint=null
。
如果打印或预览文件,改为:
StreamReader streamToPrint
,
流的概念参见第六章。
增加打印使用的字体的变量:Font printFont。 -
放PrintDocument控件到窗体,属性name为printDocument1。
-
为printDocument1增加BeginPrint事件处理函数如下:
private void printDocument1_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e) { printFont=richTextBox1.Font;//打印使用的字体 streamToPrint=new StringReader(richTextBox1.Text);//打印richTextBox1.Text } //如预览文件改为:streamToPrint=new StreamReader("文件的路径及文件名");
-
printDocument1的PrintPage事件处理函数如下。streamToPrint.ReadLine()读入一段数据,可能打印多行。本事件处理函数将此段数据打印在一行上,因此方法必须改进。
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { float linesPerPage=0;//记录每页最大行数 float yPos=0;//记录将要打印的一行数据在垂直方向的位置 i nt count=0;//记录每页已打印行数 float leftMargin=e.MarginBounds.Left;//左边距 float topMargin=e.MarginBounds.Top;//顶边距 string line=null;//从RichTextBox中读取一段字符将存到line中 //每页最大行数=一页纸打印区域的高度/一行字符的高度 linesPerPage=e.MarginBounds.Height/printFont.GetHeight(e.Graphics); //如果当前页已打印行数小于每页最大行数而且读出数据不为null,继续打印 while(count<linesPerPage&&((line=streamToPrint.ReadLine())!=null)) { //yPos为要打印的当前行在垂直方向上的位置 yPos=topMargin+(count*printFont.GetHeight(e.Graphics)); e.Graphics.DrawString(line,printFont,Brushes.Black, leftMargin,yPos,new StringFormat());//打印,参见第五章 count++;//已打印行数加1 } if(line!=null)//是否需要打印下一页 e.HasMorePages=true;//需要打印下一页 else e.HasMorePages=false;//不需要打印下一页 }
-
为printDocument1增加EndPrint事件处理函数如下:
private void printDocument1_EndPrint (object sender, System.Drawing.Printing.PrintEventArgs e) { if(streamToPrint!=null) streamToPrint.Close();//释放不用的资源 }
示例代码:
//designer文件
this.btn_Print.Click += new System.EventHandler(this.btn_Print_Click);
this.printDocument1.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.printDocument1_PrintPage);
private void btn_Print_Click(object sender, EventArgs e)
{
if (this.printDialog1.ShowDialog() == DialogResult.OK)
{
this.printDocument1.Print();
}
}
private void printDocument1_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
var g = e.Graphics;
//int page = e.PageSettings;
int count = BirthProcessData._ListBirthData.Count; //
int maxPage = (count - 24) > 0 ?( (count - 20)/ 38 )+2 : 1;
//设置高质量插值法
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
//设置高质量,低速度呈现平滑程度
g.SmoothingMode = SmoothingMode.HighQuality;
g.CompositingQuality = CompositingQuality.HighQuality;
//清空一下画布
g.Clear(Color.White);
//g.DrawImage(BirthProcessHelper.GetImage(BirthProcessData, m_Patient), new PointF(30, 30));
e.HasMorePages = true;
BirthProcessHelper.DrawBirthprocessImage(g,page);
page++;
if(page > maxPage)
{
e.HasMorePages = false;
page = 1;
}
}
特别关注:
最初的方法,直接打印图像,很不清晰
换成直接Draw
参考
C#中PrintDocument类详解
C#中PrintDocument类详解