
在当今互联网时代,大家都提倡无纸化绿色办公,如扫码,在线,小程序等,既提高了效率,又节约纸张,绿色环保,但在某些特定的场景与人群(如超市收银),打印票据或收据是必不可少。今天我们以一些简单的小例子,简述基于.NET的Windows窗体编程中打印的常见用法,仅供学习分享使用,如有不足之处,还请指正。

概述
在WinForms开发框架中,主要使用 PrintDocument 组件进行打印,而PrintPreviewDialog和PrintDialog,PageSetupDialog组件为用户提供熟悉的图形界面。主要内容如下:
- PrintDialog,是一个预配置的对话框,通过ShowDialog方法显示对话框,此控件主要用于选择打印机、选择要打印的页面,并确定基于 Windows 的应用程序中的其他打印相关设置。通过PrintDialog可以设置打印的范围,如全部打印、打印所选页面范围或打印所选内容。
- PrintDocument,用于设置描述要打印的属性以及打印的内容,然后在基于 Windows 的应用程序中打印文档,通常与PrintDialog结合使用。
- PrintPreviewControl,用于预览文档打印时的样子,它没有按钮或其他用户界面元素,因此通常仅当希望编写自己的打印预览用户界面时,才使用此控件。
- PrintPreviewDialog,此控件是一个预配置的对话框,用于预览文档在打印时的内容,它包含用于打印、放大、显示一页或多页以及关闭对话框的按钮。
- PageSetupDialog,是一个预配置的对话框,用于设置在基于 Windows 的应用程序中打印的页面详细信息,通过PageSetupDialog可以设置边框和边距调整、页眉和页脚以及纵向和横向方向。
PrintDialog
用户可以通过PrintDialog弹出的对话框,选择打印机,以及要打印的页面。PrintDialog关键属性:
- AllowCurrentPage,是否显示当前Page选项按钮,允许选择当前Page进行打印,默认为false。
- AllowPrintToFile,是否显示“打印到文件”复选框,默认为true。
- AllowSomePages,Pages选择是否可用,默认false,当为true时,可以选择打印的页码范围。
- AllowSelection,是否允许“选定范围”,默认false,当为true时,可以勾选“选定范围”复选框。
- Document,获取或设置能够从中获取PrinterSettings的文档。
- PrinterSettings,获取或设置打印机选定的打印机设置,如:设置属性Copies,可以设置打印份数,默认为1。
- PrintToFile,获取或设置“打印到文件”复选框是否勾选。
- ShowHelp,是否显示“帮助”按钮。
- ShowNetwork,是否显示“Network”按钮。
- UseEXDialog,是否显示WindowsXP风格的对话框,默认为false。
PrintDialog关键方法:
- ShowDialog,通过此方法显示打印对话框。
说明:经过验证,AllowCurrentPage,ShowNetWork两个属性在新版的操作系统中不生效。
PrintDocument
从 Windows 窗体应用程序打印时,定义一种可重用的可发送到打印机上的对象。PrintDocument关键属性:
- DefaultPageSettings,定义默认的Page设置,当All Pages被打印时默认采用此配置。
- DocumentName,定义文档名称,当打印时在状态对话框或者打印队列中,会显示此名称。
- PrinterSettings,获取或设置选择的打印机,如:设置属性Copies,可以设置打印份数,默认为1,。
PrintDocument关键事件:
- PrintPage,是PrintDocument组件最重要的事件,当调用Print方法开始打印时触发此事件,可以在此事件中编写打印逻辑。PrintPage事件包含PrintPageEventArgs参数,可以通过此参数获取Grapics对象,并通过Grapics对象绘制需要输出的内容。
- BeginPrint,当开始打印文档,且第一个Page开始打印之前触发此事件。
- EndPrint,当最后一个Page打印完成触发此事件。
PrintDocument关键方法:
- Print,调用Print方法开始打印流程。
PrintPreviewControl
PrintPreviewControl表示 Windows 窗体应用程序打印预览的原始预览部分,没有任何对话框或按钮。PrintPreviewControl控件的关键属性:
- AutoZoom,当改变控件大小,或者显示页数时,是否自动使用Zoom属性,默认为true。
- Document,设置需要预览的对象。
- Rows,Columns,控件预览时,每屏显示的行,列数量。
- Text,控件显示的文本。
- Zoom,获取或设置多大的Pages需要显示。
PrintPreviewControl的关键方法:
- InvalidatePreview,通过此方法刷新预览的文档。
PrintPreviewDialog
PrintPreviewDialog打印预览对话框,是UI框架内置的对话框,用于展示文档在打印时的外观。它包含用于打印、放大、显示一页或多页以及关闭对话框的按钮。PrintPreviewDialog控件的关键属性:
- Document,用于设置需要预览的文档对象,为PrintDocument类型的实例。
- UseAntiAlias, 是否使用抗锯齿显示文档,抗锯齿可以使文本看起来更流畅,但它也可以使显示速度变慢。
PrintPreviewDialog关键方法:
- ShowDialog,通过此方法显示打印预览对话框。
PageSetupDialog
PageSetupDialog组件是一个预配置的对话框,用于设置在基于 Windows 的应用程序中打印的页面详细信息。用户可以设置边框和边距调整、页眉和页脚以及纵向和横向方向。
- Document,获取或设置能够从中获取PageSettings的文档。
- AllowMargins,是否显示“页边距”设置选择项,默认为true。
- AllowOrientation,是否显示“方向”选择项,如横向,纵向打印,默认为true。
- AllowPaper,是否显示“纸张”选择项,如A4,B5选择等,默认为true。
- AllowPrinter,Printer按钮是否可用,默认为true。
- EnableMetric,边距是否自动在百分之英寸和毫米之间转换。
- MinMargins,最小边距,单位为百分之一英寸。
- PageSettings,打印页的设置。
- PrinterSettings,获取或设置打印机相关属性。
综合实例
完整的实现打印功能,需要结合PrintDialog,PrintDocument,PrintPreviewControl,PrintPreviewDialog,PageSetupDialog,共同完成,接下来我们通过打印功能实现一个“录取通知书”的打印。
布局UI页面
设计简单的UI页面,步骤如下:
- 通过SplitContainer控件让Form分为左右两部分,左侧用于输入信息,右侧显示打印“录取通知书”。
- 拖动PrintDocument控件到Form表单中,并命名为printDocument。
- 拖动PrintPreviewControl控件到Form表单的右侧Panel中,并命名为printPreviewControl。
- 拖动其他文本框控件,主要用于输入相关需要打印的信息。
- 拖动四个按钮,分别用于打印,预览,刷新,PageSetup。
UI布局完成后,如下所示:

初始化打印信息
在Form的Load事件中初始化PrintDocument的DetaultPageSettings,主要用于设置页大小,边距,等信息。如下所示:
private void FrmPrint_Load(object sender, EventArgs e)
{
int width_in = MM2Inch(width_p);
int height_in = MM2Inch(height_p);
PaperSize paperSize= new PaperSize("customer", width_in, height_in);
PrinterSettings printerSettings = new PrinterSettings();
printerSettings.PrintRange = PrintRange.AllPages;
printerSettings.DefaultPageSettings.PaperSize = paperSize;
PageSettings pageSetting = new PageSettings(printerSettings);
pageSetting.PaperSize = paperSize;
int margin_lr_in = MM2Inch(margin_lr);
int margin_tb_in = MM2Inch(margin_tb);
pageSetting.Margins = new Margins(margin_lr_in, margin_lr_in, margin_tb_in, margin_tb_in);
this.printDocument.DefaultPageSettings = pageSetting;
this.printPreviewControl.AutoZoom = true;
this.printPreviewControl.Zoom = 1;
}
在上述代码中用到的MM2Inch方法,主要用于毫米和百分之一英寸的换算:打印机是以百分之一英寸为单位的,单据设置是以毫米为单位的,所以需要转换,转换公式如下所示:
/// <summary>
/// 转换毫米到百分之一英寸
/// </summary>
/// <param name="mm"></param>
/// <returns></returns>
private int MM2Inch(int mm)
{
return (int)(mm * 100.0f / 25.4f);
}
打印逻辑
在PrintDocument的PrintPage事件中编写打印输出逻辑,主要通过Graphics对象输出边框,文本,图像等内容。具体如下所示:
private void printDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
{
if (e.Graphics == null)
{
return;
}
string school = this.txtSchool.Text;
string student = this.txtStudent.Text;
string department = this.txtDepartment.Text;
string beginDate = this.txtDate.Text;
string major = this.txtMajor.Text;
string tuition = this.txtTuition.Text;
string seal = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, this.txtSeal.Text);
Graphics g = e.Graphics;
Font defaultFont = new Font("Arial", 14f, FontStyle.Regular);
Font schoolFont = new Font("宋体", 18f, FontStyle.Bold);
Font keyFont = new Font("宋体", 16f, FontStyle.Bold | FontStyle.Underline);
Font titleFont = new Font("Arial", 20f, FontStyle.Bold);
Font qianMingFont = new Font("Rage Italic", 20f, FontStyle.Bold | FontStyle.Underline);
Brush defaultBrush = Brushes.Black;
g.DrawRectangle(Pens.Red, new RectangleF(new PointF(3, 3), new SizeF(466, 505)));
g.DrawString(school, schoolFont, defaultBrush, new Point(10, 20));
g.DrawString("录取通知书", titleFont, Brushes.Red, new Point(130, 70));
g.DrawString($"_{student}_", keyFont, defaultBrush, new Point(10, 120));
g.DrawString("同学:", defaultFont, defaultBrush, new Point(100, 120));
g.DrawString("我校决定录取你入", defaultFont, defaultBrush, new Point(10, 170));
g.DrawString($"_{department}_", keyFont, defaultBrush, new Point(190, 170));
g.DrawString("学院(系)", defaultFont, defaultBrush, new Point(300, 170));
g.DrawString($"_{major}_", keyFont, defaultBrush, new Point(10, 220));
g.DrawString("专业学习。学费", defaultFont, defaultBrush, new Point(220, 220));
g.DrawString($"_{tuition}_", keyFont, defaultBrush, new Point(10, 270));
g.DrawString("元整,请你准时于", defaultFont, defaultBrush, new Point(95, 270));
g.DrawString($"_{beginDate}_", keyFont, defaultBrush, new Point(260, 270));
g.DrawString("之前到校报到。", defaultFont, defaultBrush, new Point(10, 320));
g.DrawString(school, defaultFont, defaultBrush, new Point(220, 400));
g.DrawString("2026 年 06 月 06 日", defaultFont, defaultBrush, new Point(210, 440));
g.DrawImage(Image.FromFile(seal), new Point(220, 330));
g.DrawString("校长:", defaultFont, defaultBrush, new Point(20, 420));
g.DrawString("okcoder", qianMingFont, defaultBrush, new Point(80, 415));
}
页面刷新
右侧通过PrintPreviewControl实现显示打印通知书功能,通过此控件的InvalidatePreview方法实现控件的刷新,如下所示:
private void btnRefresh_Click(object sender, EventArgs e)
{
this.printPreviewControl.InvalidatePreview();
}
实现效果如下所示:

打印预览
通过PrintPreviewDialog控件实现打印预览,此控件会弹出打印预览对话框,显示打印的内容,如下所示:
private void btnPreview_Click(object sender, EventArgs e)
{
PrintPreviewDialog printPreviewDialog = new PrintPreviewDialog();
printPreviewDialog.Document = this.printDocument;
printPreviewDialog.Width = this.printPreviewControl.Width + 30;
printPreviewDialog.Height = this.printPreviewControl.Height + 50;
printPreviewDialog.AutoScaleMode = AutoScaleMode.None;
printPreviewDialog.PrintPreviewControl.AutoZoom = false;
printPreviewDialog.PrintPreviewControl.Zoom = 1;
printPreviewDialog.ShowDialog();
}
点击预览按钮,效果如下所示:

打印
打印功能通过PrintDialog对话框,选择和设置打印的相关信息,然后再调用PrintDocument对象的Print方法开始打印过程,如下所示:
private void btnPrint_Click(object sender, EventArgs e)
{
PrintDialog printDialog = new PrintDialog();
printDialog.Document = this.printDocument;
printDialog.AllowCurrentPage = true;
printDialog.AllowPrintToFile = true;
printDialog.AllowSomePages = true;
printDialog.AllowSelection = true;
printDialog.ShowHelp = true;
printDialog.ShowNetwork = true;
printDialog.UseEXDialog = false;
printDialog.PrinterSettings = this.printDocument.DefaultPageSettings.PrinterSettings;
if (printDialog.ShowDialog() == DialogResult.OK)
{
this.printDocument.Print();
}
}
点击“打印”按钮,弹出打印对话框,如下所示:

PageSetup
打印页的设置通过PageSetupDialog弹出打印页设置对话框,如下所示:
private void btnPageSetup_Click(object sender, EventArgs e)
{
PageSetupDialog pageSetupDialog = new PageSetupDialog();
pageSetupDialog.AllowMargins = true;
pageSetupDialog.AllowOrientation = true;
pageSetupDialog.AllowPaper = true;
pageSetupDialog.AllowPrinter = true;
pageSetupDialog.EnableMetric = true;
pageSetupDialog.Document = this.printDocument;
pageSetupDialog.MinMargins = new Margins(3, 3, 3, 3);
if(pageSetupDialog.ShowDialog()==DialogResult.OK)
{
if (pageSetupDialog.PageSettings != null)
{
this.printDocument.DefaultPageSettings = pageSetupDialog.PageSettings;
}
}
}
点击PageSetup按钮,效果如下所示:

源码获取
关于本系列的完整代码,可以通过gitee上的库进行获取:https://gitee.com/ahsiang/winforms

以上就是《基于.NET的Windows窗体编程之WinForms打印》的全部内容,旨在抛砖引玉,一起学习,共同进步。
文章摘自:https://www.cnblogs.com/hsiang/p/20112765
