基于.NET的Windows窗体编程之WinForms打印


在当今互联网时代,大家都提倡无纸化绿色办公,如扫码,在线,小程序等,既提高了效率,又节约纸张,绿色环保,但在某些特定的场景与人群(如超市收银),打印票据或收据是必不可少。今天我们以一些简单的小例子,简述基于.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页面,步骤如下:

  1. 通过SplitContainer控件让Form分为左右两部分,左侧用于输入信息,右侧显示打印“录取通知书”。
  2. 拖动PrintDocument控件到Form表单中,并命名为printDocument。
  3. 拖动PrintPreviewControl控件到Form表单的右侧Panel中,并命名为printPreviewControl。
  4. 拖动其他文本框控件,主要用于输入相关需要打印的信息。
  5. 拖动四个按钮,分别用于打印,预览,刷新,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