为打印预览对话框 PrintPreviewDialog 添加保存到 PDF 文件按钮源代码详解
为打印预览对话框 PrintPreviewDialog 添加保存到 PDF 文件按钮源代码详解
- 前言
- 1、创建自定义打印预览对话框 CustomPrintPreviewDialog
- 2、自定义打印预览对话框内部按钮和事件
- 2.1、自定义打印预览对话框内部按钮和事件
- 2.2、公共静态类和打印预览分类枚举
- 2.3、主窗调用自定义打印预览对话框
- 3、自定义打印预览对话框外部按钮
- 3.1、自定义打印预览对话框外部按钮
- 3.2、公共静态类和打印预览分类枚举
- 3.3、主窗调用自定义打印预览对话框
前言
以 Windows 平台 Visual Studio 2017 C# 为开发工具,Windows Forms(.Net FrameWork 4.0)为框架,创建创建自定义打印预览对话框,并添加自定义按钮,以将打印文档内容保存到 PDF 文件。
1、创建自定义打印预览对话框 CustomPrintPreviewDialog
在项目中添加类,命名为 CustomPrintPreviewDialog : PrintPreviewDialog
using System;
using System.Drawing;
using System.Drawing.Printing;
using System.Windows.Forms;
namespace 命名空间
{public partial class CustomPrintPreviewDialog : PrintPreviewDialog//以原始打印预览为基类{}
}
2、自定义打印预览对话框内部按钮和事件
2.1、自定义打印预览对话框内部按钮和事件
using static 命名空间.PublicStaticClass;namespace 命名空间
{public partial class CustomPrintPreviewDialog : PrintPreviewDialog{/// <summary>页面设置</summary>private PageSetupDialog pageSetupDialog = new PageSetupDialog();/// <summary>当前打印文档</summary>private PrintDocument CurrentDocument;/// <summary>获取和设置当前打印文档</summary>public new PrintDocument Document{get => CurrentDocument;set{CurrentDocument = value;base.Document = value;}}/// <summary>自定义打印预览对话框</summary>public CustomPrintPreviewDialog(){// 获取打印预览对话框原生工具栏if (!(this.Controls["toolStrip1"] is ToolStrip toolStrip)) return;//初始化页面设置pageSetupDialog = new PageSetupDialog{EnableMetric = true//打开毫米为单位,否则为1/100英寸};// 添加页面设置按钮,和内部单击事件ToolStripButton PrintSettingsButton = new ToolStripButton("页面设置", null, (s, e) => PrintSettingsButton_Click()){DisplayStyle = ToolStripItemDisplayStyle.ImageAndText,// 显示样式Image = Properties.Resources.PageSetup,//自定义按钮图标图像ImageScaling = ToolStripItemImageScaling.SizeToFit,Size = new Size(120, 40),// 设置按钮大小Margin = new Padding(20, 2, 5, 2),// 设置边距控制位置Alignment = ToolStripItemAlignment.Left,//.Right// 设置对齐方式};toolStrip.Items.Insert(0, PrintSettingsButton);//插入到PrintPreviewDialog工具栏最前面// 添加保存为PDF文件按钮,和内部单击事件ToolStripButton SavePDFButton = new ToolStripButton("保存为 PDF", null, (s, e) => PrintToPDF()){DisplayStyle = ToolStripItemDisplayStyle.ImageAndText,Image = Properties.Resources.PDFFile,ImageScaling = ToolStripItemImageScaling.SizeToFit,ToolTipText = "保存为 PDF 文件"};toolStrip.Items.Insert(10, SavePDFButton);//插入第10个图标位置}/// <summary>打印设置按钮单击</summary>private void PrintSettingsButton_Click(){pageSetupDialog.Document = this.PrintPreviewControl.Document;pageSetupDialog.PageSettings = this.PrintPreviewControl.Document.DefaultPageSettings;if (pageSetupDialog.ShowDialog() == DialogResult.OK){this.Document.DefaultPageSettings = pageSetupDialog.PageSettings;this.PrintPreviewControl.InvalidatePreview();//刷新预览}}/// <summary>打印到PDF文件</summary>private void PrintToPDF(){if (CurrentDocument == null){MessageBox.Show("没有可打印的文档", "提示",MessageBoxButtons.OK, MessageBoxIcon.Warning);return;}string PDFFilePath = string.Empty;switch (printResultTableType){case PrintResultTableType.AdcpDischargeMeasureResults:PDFFilePath = SiteMeasureResultsFile.Replace(".SRF", "_ADCP流量测验记载表.PDF");break;case PrintResultTableType.AdcpVelocityDirectionResults:PDFFilePath = SiteMeasureResultsFile.Replace(".SRF", "_ADCP流速流向成果表.PDF");break;case PrintResultTableType.PrintPreviewFormGraphics:if (string.IsNullOrEmpty(ProjectDirectory)){PDFFilePath = Application.StartupPath + $"\\{ActiveFormName}窗体图形.PDF";}else{PDFFilePath = ProjectDirectory + $"\\{ActiveFormName}窗体图形.PDF";}break;case PrintResultTableType.PrintPreviewGraphics:if (string.IsNullOrEmpty(ProjectDirectory)){PDFFilePath = Application.StartupPath + $"\\{ActiveFormName}图形.PDF";}else{PDFFilePath = ProjectDirectory + $"\\{ActiveFormName}图形.PDF";}break;}string PrinterString = string.Empty;if (CheckPdfPrinterExists(out PrinterString)){using (PrintDialog printDialog = new PrintDialog()){// 配置打印设置PrinterSettings printerSettings = new PrinterSettings{PrinterName = PrinterString,//PDF 虚拟打印机名称PrintToFile = true,//打开打印到文件PrintFileName = PDFFilePath//打印的PDF文件路径名称};printDialog.Document = CurrentDocument;printDialog.PrinterSettings = printerSettings;// printDialog.UseEXDialog = true;// 执行打印CurrentDocument.PrinterSettings = printerSettings;CurrentDocument.Print();MessageBox.Show($"PDF文件已成功保存到:\r\n\r\n{PDFFilePath}", "导出成功", MessageBoxButtons.OK, MessageBoxIcon.Information);}}else{MessageBox.Show("未找到 Adobe 或微软 PDF 打印机","提示", MessageBoxButtons.OK, MessageBoxIcon.Information); }}/// <summary>检查 PDF虚拟打印机</summary>/// <param name="PrinterString">输出 PDF 打印机名称</param>/// <returns>返回是否存在 PDF 虚拟打印机</returns>private bool CheckPdfPrinterExists(out string PrinterString){foreach (string printer in PrinterSettings.InstalledPrinters){if (printer.Contains("Microsoft Print to PDF") || printer.Contains("Adobe PDF") || printer.Contains("Acrobat Distiller")){PrinterString = printer;return true;}}PrinterString = string.Empty;return false;}}
}
2.2、公共静态类和打印预览分类枚举
namespace 命名空间
{/// <summary>公共静态类</summary>public static class PublicStaticClass{/// <summary>打印表类型</summary>public static PrintResultTableType printResultTableType;///<summary>活动窗体名称</summary>public static string ActiveFormName = string.Empty;}/// <summary>打印成果表类型</summary>public enum PrintResultTableType{/// <summary>打印预览ADCP流量测验成果表</summary>AdcpDischargeMeasureResults = 0,/// <summary>打印预览ADCP流速流向成果表</summary>AdcpVelocityDirectionResults = 1,/// <summary>打印预览图形</summary>PrintPreviewGraphics = 2,/// <summary>打印预览窗体图形</summary>PrintPreviewFormGraphics = 3,}
}
2.3、主窗调用自定义打印预览对话框
主窗体为MDI,以打印子窗体图像为例。
using static 命名空间.PublicStaticClass;
namespace 命名空间
{public partial class AdcpProcesMainForm : Form{/// <summary>打印文档</summary>private PrintDocument PrintDocument = null;public AdcpProcesMainForm(){InitializeComponent();this.MdiChildActivate += OnMdiChildActivated;}/// <summary>当前活动子窗口</summary>/// <param name="sender"></param>/// <param name="e"></param>private void OnMdiChildActivated(object sender, EventArgs e){var activeChild = this.ActiveMdiChild;if (activeChild != null){ActiveFormName =activeChild.Text;}}private void PrintPreviewFormGraphicsMenu_Click(object sender, EventArgs e){var activeChild = this.ActiveMdiChild;if (this.ActiveMdiChild != null){printResultTableType = PrintResultTableType.PrintPreviewFormGraphics;//this.Hide();//隐藏主窗,配合Preview.FormClosed。PrintDocument = new PrintDocument();// 自定义打印预览CustomPrintPreviewDialog Preview = new CustomPrintPreviewDialog{// ShowIcon = false,StartPosition = FormStartPosition.CenterScreen,WindowState = FormWindowState.Maximized,Icon = Properties.Resources.AdcpTable, // 设置自定义打印预览图标Text = "窗体打印预览", // 设置窗口标题Height = Screen.PrimaryScreen.Bounds.Height,Width = Screen.PrimaryScreen.Bounds.Width,FormBorderStyle = FormBorderStyle.FixedDialog,};// 捕获子窗体的图形区域Bitmap FormImage = new Bitmap(activeChild.Width, activeChild.Height);activeChild.DrawToBitmap(FormImage, new Rectangle(0, 0, FormImage.Width, FormImage.Height));PrintDocument.PrintPage += (s, args) =>{// 计算居中打印位置Rectangle printArea = args.MarginBounds;if (FormImage.Width > printArea.Width || FormImage.Height > printArea.Height){// 按比例缩放Size newSize = FitSize(FormImage.Size, printArea.Size);int x = printArea.X + (printArea.Width - newSize.Width) / 2;int y = printArea.Y + (printArea.Height - newSize.Height) / 2;args.Graphics.DrawImage(FormImage,new Rectangle(x, y, newSize.Width, newSize.Height));}else{// 居中打印int x = printArea.X + (printArea.Width - FormImage.Width) / 2;int y = printArea.Y + (printArea.Height - FormImage.Height) / 2;args.Graphics.DrawImage(FormImage, x, y);}};/// <summary>打印预览窗体关闭后,恢复主窗显示</summary>//Preview.FormClosed += (s, args) =>// {// this.Show(); // 预览关闭时重新显示主窗体// this.Activate(); // 激活主窗体获得焦点// };Preview.Document = PrintDocument;if (FormImage.Width > FormImage.Height){Preview.Document.DefaultPageSettings.Landscape = true;Preview.Landscape = true;}else{Preview.Document.DefaultPageSettings.Landscape = false;Preview.Landscape = false;}Preview.ShowDialog(this);}}}
}
3、自定义打印预览对话框外部按钮
3.1、自定义打印预览对话框外部按钮
namespace 命名空间
{public partial class CustomPrintPreviewDialog : PrintPreviewDialog{/// <summary>页面设置</summary>private PageSetupDialog pageSetupDialog = new PageSetupDialog();/// <summary>保存到PDF按钮事件</summary>public event EventHandler SavePDFButtonClick;/// <summary>自定义打印预览对话框</summary>public CustomPrintPreviewDialog(){// 获取打印预览对话框原生工具栏if (!(this.Controls["toolStrip1"] is ToolStrip toolStrip)) return;//初始化页面设置pageSetupDialog = new PageSetupDialog{EnableMetric = true//打开毫米为单位,否则为1/100英寸};// 添加页面设置按钮,和内部单击事件ToolStripButton PrintSettingsButton = new ToolStripButton("页面设置", null, (s, e) => PrintSettingsButton_Click()){DisplayStyle = ToolStripItemDisplayStyle.ImageAndText,// 显示样式Image = Properties.Resources.PageSetup,//自定义按钮图标图像ImageScaling = ToolStripItemImageScaling.SizeToFit,Size = new Size(120, 40),// 设置按钮大小Margin = new Padding(20, 2, 5, 2),// 设置边距控制位置Alignment = ToolStripItemAlignment.Left,//.Right// 设置对齐方式};toolStrip.Items.Insert(0, PrintSettingsButton);//插入到PrintPreviewDialog工具栏最前面// 添加保存为PDF文件按钮,和外部单击事件ToolStripButton SavePDFButton = new ToolStripButton("保存为 PDF", null, (s, e) => SavePDFButtonClick?.Invoke(this, e)){DisplayStyle = ToolStripItemDisplayStyle.ImageAndText,Image = Properties.Resources.PDFFile,ImageScaling = ToolStripItemImageScaling.SizeToFit,ToolTipText = "保存为 PDF 文件"};toolStrip.Items.Insert(10, SavePDFButton);//插入第10个图标位置}/// <summary>打印设置按钮单击</summary>private void PrintSettingsButton_Click(){pageSetupDialog.Document = this.PrintPreviewControl.Document;pageSetupDialog.PageSettings = this.PrintPreviewControl.Document.DefaultPageSettings;if (pageSetupDialog.ShowDialog() == DialogResult.OK){this.Document.DefaultPageSettings = pageSetupDialog.PageSettings;this.PrintPreviewControl.InvalidatePreview();//刷新预览}}}
}
3.2、公共静态类和打印预览分类枚举
namespace 命名空间
{/// <summary>公共静态类</summary>public static class PublicStaticClass{/// <summary>打印表类型</summary>public static PrintResultTableType printResultTableType;///<summary>活动窗体名称</summary>public static string ActiveFormName = string.Empty;}/// <summary>打印成果表类型</summary>public enum PrintResultTableType{/// <summary>打印预览ADCP流量测验成果表</summary>AdcpDischargeMeasureResults = 0,/// <summary>打印预览ADCP流速流向成果表</summary>AdcpVelocityDirectionResults = 1,/// <summary>打印预览图形</summary>PrintPreviewGraphics = 2,/// <summary>打印预览窗体图形</summary>PrintPreviewFormGraphics = 3,}
}
3.3、主窗调用自定义打印预览对话框
namespace 命名空间
{public partial class AdcpProcesMainForm : Form{/// <summary>打印文档</summary>private PrintDocument PrintDocument = null;public AdcpProcesMainForm(){InitializeComponent();this.MdiChildActivate += OnMdiChildActivated;}/// <summary>当前活动子窗口</summary>/// <param name="sender"></param>/// <param name="e"></param>private void OnMdiChildActivated(object sender, EventArgs e){var activeChild = this.ActiveMdiChild;if (activeChild != null){ActiveFormName =activeChild.Text;}}private void PrintPreviewFormGraphicsMenu_Click(object sender, EventArgs e){var activeChild = this.ActiveMdiChild;if (this.ActiveMdiChild != null){printResultTableType = PrintResultTableType.PrintPreviewFormGraphics;//this.Hide();PrintDocument = new PrintDocument();// 打印预览CustomPrintPreviewDialog Preview = new CustomPrintPreviewDialog{// ShowIcon = false,StartPosition = FormStartPosition.CenterScreen,WindowState = FormWindowState.Maximized,Icon = Properties.Resources.AdcpTable, // 设置系统信息图标Text = "窗体打印预览", // 设置窗口标题Height = Screen.PrimaryScreen.Bounds.Height,Width = Screen.PrimaryScreen.Bounds.Width,FormBorderStyle = FormBorderStyle.FixedDialog,};// 捕获子窗体的图形区域Bitmap FormImage = new Bitmap(activeChild.Width, activeChild.Height);//Bitmap FormImage = new Bitmap(activeChild.ClientSize.Width, activeChild.ClientSize.Height );activeChild.DrawToBitmap(FormImage, new Rectangle(0, 0, FormImage.Width, FormImage.Height));PrintDocument.PrintPage += (s, args) =>{// 计算居中打印位置Rectangle printArea = args.MarginBounds;if (FormImage.Width > printArea.Width || FormImage.Height > printArea.Height){// 按比例缩放Size newSize = FitSize(FormImage.Size, printArea.Size);int x = printArea.X + (printArea.Width - newSize.Width) / 2;int y = printArea.Y + (printArea.Height - newSize.Height) / 2;args.Graphics.DrawImage(FormImage,new Rectangle(x, y, newSize.Width, newSize.Height));}else{// 居中打印int x = printArea.X + (printArea.Width - FormImage.Width) / 2;int y = printArea.Y + (printArea.Height - FormImage.Height) / 2;args.Graphics.DrawImage(FormImage, x, y);}};//Preview.FormClosed += (s, args) =>// {// this.Show(); // 预览关闭时重新显示主窗体// this.Activate(); // 激活主窗体获得焦点// };Preview.Document = PrintDocument;if (FormImage.Width > FormImage.Height){Preview.Document.DefaultPageSettings.Landscape = true;Preview.Landscape = true;}else{Preview.Document.DefaultPageSettings.Landscape = false;Preview.Landscape = false;}Preview.SavePDFButtonClick += SavePDFButton_Click;//按钮事件Preview.ShowDialog(this);//}}/// <summary>保存为PDF文件</summary>/// <param name="sender"></param>/// <param name="e">事件基类</param>private void SavePDFButton_Click(object sender, EventArgs e){string PrinterString = string.Empty;if (CheckPdfPrinterExists(out PrinterString))//检查和获取PDF虚拟打印机名称{string PDFFilePath = string.Empty;switch (printResultTableType){case PrintResultTableType.AdcpDischargeMeasureResults:PDFFilePath = SiteMeasureResultsFile.Replace(".SRF", "_ADCP流量测验记载表.PDF");break;case PrintResultTableType.AdcpVelocityDirectionResults:PDFFilePath = SiteMeasureResultsFile.Replace(".SRF", "_ADCP流速流向成果表.PDF");break;case PrintResultTableType.PrintPreviewFormGraphics:if (string.IsNullOrEmpty(ProjectDirectory)){PDFFilePath = Application.StartupPath + $"\\{ActiveFormName}窗体图形.PDF";}else{PDFFilePath = ProjectDirectory + $"\\{ActiveFormName}窗体图形.PDF";}break;case PrintResultTableType.PrintPreviewGraphics:if (string.IsNullOrEmpty(ProjectDirectory)){PDFFilePath = Application.StartupPath + $"\\{ActiveFormName}图形.PDF";}else{PDFFilePath = ProjectDirectory + $"\\{ActiveFormName}图形.PDF";}break;}if (PrintDocument != null){using (PrintDialog printDialog = new PrintDialog()){// 配置打印设置PrinterSettings printerSettings = new PrinterSettings{PrinterName = PrinterString,//PDF 虚拟打印机名称PrintToFile = true,//打开打印到文件PrintFileName = PDFFilePath//打印的PDF文件路径名称};printDialog.Document = PrintDocument;printDialog.PrinterSettings = printerSettings;// printDialog.UseEXDialog = true;// 执行打印PrintDocument.PrinterSettings = printerSettings;PrintDocument.Print();MessageBox.Show($"PDF文件已成功保存到:\r\n\r\n{PDFFilePath}", "导出成功", MessageBoxButtons.OK, MessageBoxIcon.Information);}}}else{//throw new Exception("未找到 Adobe 或微软 PDF 打印机");MessageBox.Show("未找到 Adobe 或微软 PDF 打印机", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);}}/// <summary>检查 PDF虚拟打印机</summary>/// <param name="PrinterString">输出 PDF 打印机名称</param>/// <returns>返回是否存在 PDF 虚拟打印机</returns>private bool CheckPdfPrinterExists(out string PrinterString){foreach (string printer in PrinterSettings.InstalledPrinters){if (printer.Contains("Microsoft Print to PDF") || printer.Contains("Adobe PDF") || printer.Contains("Acrobat Distiller")){PrinterString = printer;return true;}}PrinterString = string.Empty;return false;}}
}