C# 使用自带的组件PrintPreviewDialog 和 PrintDocument实现打印预览(一) 您所在的位置:网站首页 页眉和页脚默认作用范围是什么 C# 使用自带的组件PrintPreviewDialog 和 PrintDocument实现打印预览(一)

C# 使用自带的组件PrintPreviewDialog 和 PrintDocument实现打印预览(一)

2023-05-26 07:13| 来源: 网络整理| 查看: 265

文章目录 前言相关内容了解打印预览功能1 创建winform工程2 创建要打印的测试数据3 绘制打印页绘制页脚绘制内容PrintPage事件 完整的代码工程小节

前言

有这么个需求:DataTable中有一些数据是需要给显示或直接可以连接打印机进行打印的, 查阅了一下资料,发现官方就有组件PrintPreviewDialog和PrintDocument能实现这个功能。

相关内容了解

1 PrintPreviewDialog是一个打印预览的对话框,有打印,缩放、页面显示、选择页数、关闭等按钮。 长得就是这个样子。 在这里插入图片描述 2 PrintDocument类:是一个可以发送到打印机上的对象

3 PrintDocument.PrintPage 事件 当需要为当前页打印的输出时发生 4 PaperSize 类 指定纸张的大小 5 PageSettings.PaperSize 属性 获取或设置该页的纸张大小 6 PrinterSettings 类 指定打印时如何打印文档的信息,包括打印文档的打印机 7 PaperKind 枚举 指定标准纸张大小

8 Margins 类 指定打印页的边距尺寸

左上角的坐标点是(MarginBounds.X, MarginBounds.Y)

e.MarginBounds.Right = e.MarginBounds.Left + e.MarginBounds.Width e.MarginBounds.Bottom = e.MarginBounds.Top + e.MarginBounds.Height

在这里插入图片描述 具体可以查看MSDN的介绍: 1、PrintDocument 类 https://learn.microsoft.com/zh-cn/dotnet/api/system.drawing.printing.printdocument?view=dotnet-plat-ext-7.0 2、Margins 类 https://learn.microsoft.com/zh-cn/dotnet/api/system.drawing.printing.margins?view=dotnet-plat-ext-7.0

打印预览功能 1 创建winform工程

先创建一个winform工程,在窗体上放置了一个Button,名称是btnPreView打印预览的入口按钮, 还有一个PrintDocument组件,名称是myDocument用于呈现要打印的内容。

在这里插入图片描述

2 创建要打印的测试数据

使用一个全局DataTable 名为saveTable存放测试数据。这里创建了100 行* 5列的数据,每列分别是 序号、名称、当前值、描述和默认值这五列。当然这只是我赋予的意义,为了好记而已。

/// /// 构建临时数据表 /// /// private DataTable CreateTable() { DataTable dt = new DataTable(); DataColumn col1 = new DataColumn("Num", typeof(string)); //序号 DataColumn col2 = new DataColumn("Name", typeof(string)); //名称 DataColumn col3 = new DataColumn("Val", typeof(string)); //当前值 DataColumn col4 = new DataColumn("Des", typeof(string)); //描述 DataColumn col5 = new DataColumn("Set", typeof(string)); //默认值 dt.Columns.Add(col1); dt.Columns.Add(col2); dt.Columns.Add(col3); dt.Columns.Add(col4); dt.Columns.Add(col5); Random random = new Random(); List nameList = new List { "A", "BB", "CCC", "D", "E", "F", "G","H","II", "JJ", "LL", "M" }; List tempList = new List { "dsd", "sdfdgvre", "Hello", "Gilrs", "Today", "YYYY", "dfgre","GSD","fdgfer", "Wesd", "DLG", "fsdahfi;o" }; for (int i = 0; i DataRow dr = dt.NewRow(); //序号 dr[0] = "KK" + i.ToString("d2") + "." + j.ToString("d2"); //名称 dr[1] = nameList[j]; //当前值 if (j % 3 == 0) { dr[2] = random.NextDouble().ToString("f3"); } else { dr[2] = i * j - random.Next(0, 30); } //描述 dr[3] = tempList[j]; //出厂值 dr[4] = random.NextDouble().ToString("f2"); //添加新行 dt.Rows.Add(dr); } } return dt; } 3 绘制打印页

这里的绘制分为三个部分,表头、内容和页脚。绘制方法都是大同小异,只是为了模块化,划分了不同区域。使用Draw绘制,重要的是找到要绘制点的X 、Y 坐标,通过MeasureString计算字体的高度, 其余的功能都还比较简单。 先看一下要打印的模板,类似下图。在这里插入图片描述

绘制标题(页眉) 序号 名称

/// /// 绘制标题头 /// /// 绘图对象 /// Y轴坐标 /// 字符串格式 private void DrawTitle(System.Drawing.Printing.PrintPageEventArgs e, int tempTop, StringFormat tempFormat) { //绘制水平线 e.Graphics.DrawLine(Pens.Black, new Point(e.MarginBounds.Left, tempTop), new Point(e.MarginBounds.Right, tempTop)); Font printFont = new Font(fontName, fontNum); //计算字体的高度 K00ARk, 根据使用到的字进行组合成串 int fontHeight = (int)(e.Graphics.MeasureString("K00ARk", printFont).Height); //画刷 SolidBrush brush = new SolidBrush(Color.Black); //填充背景色 e.Graphics.FillRectangle(Brushes.LightBlue, new RectangleF(e.MarginBounds.Left, tempTop, e.MarginBounds.Width, fontHeight)); //列的序号 int col = 0; //列 序号 string drawString = TitleStr[col]; //矩形框 RectangleF rectangle = new RectangleF((int)cellLeft[col], tempTop, (int)cellWidth[col], fontHeight); e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 名称 drawString = TitleStr[col]; //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 设定值 drawString = TitleStr[col]; //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 默认值 drawString = TitleStr[col]; //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); } 绘制页脚

在底部添加公司信息和页码作为页脚。

/// /// 绘制页脚 /// /// 绘图对象 /// 页面序号 private void DrawFooter(System.Drawing.Printing.PrintPageEventArgs e, int pageNo) { Font font = new Font("微软雅黑", 10); //绘制直线 e.Graphics.DrawLine(new Pen(Color.Black, 1), new Point(e.MarginBounds.Left, e.MarginBounds.Bottom), new Point(e.MarginBounds.Right, e.MarginBounds.Bottom)); //公司信息标注 string tempStr = "Test for Windows(C) by 唠嗑一夏 Electric Corporation"; e.Graphics.DrawString(tempStr, font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Bottom+2); //页脚序号 tempStr = pageNo.ToString(); e.Graphics.DrawString(tempStr, font, Brushes.Black, e.MarginBounds.Right - e.Graphics.MeasureString(tempStr, font).Width, e.MarginBounds.Bottom+2); } 绘制内容

一行一行的绘制DataTable中的数据内容。

/// /// 绘制内容 /// /// 绘图对象 /// 数据行索引 /// Y轴坐标 /// 字符串格式 private void DrawContent(System.Drawing.Printing.PrintPageEventArgs e, int printIndex, int tempTop, StringFormat tempFormat) { Font printFont = new Font(fontName, fontNum); //计算字体的高度 K00ARk, 根据使用到的字进行组合成串 int fontHeight = (int)(e.Graphics.MeasureString("K00ARk", printFont).Height); //画刷 SolidBrush brush = new SolidBrush(Color.Black); //列的序号 int col = 0; //列 序号 string drawString = saveTable.Rows[printIndex][0].ToString() + saveTable.Rows[printIndex][1].ToString(); //矩形框 RectangleF rectangle = new RectangleF((int)cellLeft[col], tempTop, (int)cellWidth[col], fontHeight); e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 名称 drawString = saveTable.Rows[printIndex][3].ToString(); //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 设定值 drawString = saveTable.Rows[printIndex][2].ToString(); //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 默认值 drawString = saveTable.Rows[printIndex][4].ToString(); //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); } PrintPage事件

计算每列占的比例,在事件中判断是否需要换页以及是否绘制结束。

/// /// 当前页打印发生的事件 /// /// /// private void MyDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //页面大小 PaperSize pageSize = e.PageSettings.PaperSize; //根据页面大小,按比例划分列宽 //序号 cellWidth[0] = (float)(pageSize.Width * 0.098); //描述 cellWidth[1] = (float)(pageSize.Width * 0.36); //当前值 cellWidth[2] = (float)(pageSize.Width * 0.2); //出厂值 cellWidth[3] = (float)(pageSize.Width * 0.1176); //计算列的起始位置 cellLeft[0] = e.PageSettings.Margins.Left; cellLeft[1] = cellLeft[0] + cellWidth[0]; cellLeft[2] = cellLeft[1] + cellWidth[1]; cellLeft[3] = cellLeft[2] + cellWidth[2]; //高度 int tempTop = e.MarginBounds.Top; //是否新的页面 bool tempIsNewPage = true; //设置打印字符串的格式 StringFormat tempStrFormat = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter }; //设置字体 Font printFont = new Font("宋体", 9); //计算字体的高度 int fontHeight = (int)e.Graphics.MeasureString("KK00.10序号", printFont).Height; //指定高质量、低速度呈现 e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; try { string printStr; while(printPoint //判断当前打印是否超出页面范围,决定是否换页 //打印页脚 DrawFooter(e, PageNo); PageNo++; //继续分页打印 e.HasMorePages = true; return; } //打印当前页的内容 //KK00.00 printStr = saveTable.Rows[printPoint][0].ToString().Substring(5); if (printStr.Equals("00") || tempIsNewPage) {//一组数据的开始 tempIsNewPage = false; tempTop += 2; //绘制标题 DrawTitle(e, tempTop, tempStrFormat); tempTop += fontHeight; } //绘制内容 DrawContent(e, printPoint, tempTop, tempStrFormat); //更新Y轴高度 tempTop += fontHeight; //序号自增 printPoint++; //判断是否已经到终点 if(printPoint >= saveTable.Rows.Count) { //绘制页脚 DrawFooter(e, PageNo); //重置打印参数 PageNo = 1; printPoint = 0; return; } } } catch { } } 完整的代码工程

下面是完整的代码工程,设计界面的代码就不列出来了。

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Printing; using System.Linq; using System.Text; using System.Windows.Forms; namespace PrintDemo { public partial class Form1 : Form { //打印序号 int printPoint = 0; //页码 int PageNo = 1; //表头名称 string[] TitleStr = new string[] { "序号", "名称", "当前值", "出厂值" }; //列宽 float[] cellWidth = new float[4]; //列左侧的起始位置 float[] cellLeft = new float[4]; //数据表 DataTable saveTable; string fontName = "宋体"; int fontNum = 9; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { //数据 saveTable = CreateTable(); //打印预览按钮 btnPreView.Click += BtnPreView_Click; //当前页打印发生的事件 myDocument.PrintPage += MyDocument_PrintPage; } /// /// 构建临时数据表 /// /// private DataTable CreateTable() { DataTable dt = new DataTable(); DataColumn col1 = new DataColumn("Num", typeof(string)); //序号 DataColumn col2 = new DataColumn("Name", typeof(string)); //名称 DataColumn col3 = new DataColumn("Val", typeof(string)); //当前值 DataColumn col4 = new DataColumn("Des", typeof(string)); //描述 DataColumn col5 = new DataColumn("Set", typeof(string)); //默认值 dt.Columns.Add(col1); dt.Columns.Add(col2); dt.Columns.Add(col3); dt.Columns.Add(col4); dt.Columns.Add(col5); Random random = new Random(); List nameList = new List { "A", "BB", "CCC", "D", "E", "F", "G","H","II", "JJ", "LL", "M" }; List tempList = new List { "dsd", "sdfdgvre", "Hello", "Gilrs", "Today", "YYYY", "dfgre","GSD","fdgfer", "Wesd", "DLG", "fsdahfi;o" }; for (int i = 0; i DataRow dr = dt.NewRow(); //序号 dr[0] = "KK" + i.ToString("d2") + "." + j.ToString("d2"); //名称 dr[1] = nameList[j]; //当前值 if (j % 3 == 0) { dr[2] = random.NextDouble().ToString("f3"); } else { dr[2] = i * j - random.Next(0, 30); } //描述 dr[3] = tempList[j]; //出厂值 dr[4] = random.NextDouble().ToString("f2"); //添加新行 dt.Rows.Add(dr); } } return dt; } /// /// 打印预览 /// /// /// private void BtnPreView_Click(object sender, EventArgs e) { //打印预览对话框 PrintPreviewDialog dialog = new PrintPreviewDialog(); dialog.Document = myDocument; dialog.ShowIcon = false; dialog.ShowDialog(); } /// /// 当前页打印发生的事件 /// /// /// private void MyDocument_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e) { //页面大小 PaperSize pageSize = e.PageSettings.PaperSize; //根据页面大小,按比例划分列宽 //序号 cellWidth[0] = (float)(pageSize.Width * 0.098); //描述 cellWidth[1] = (float)(pageSize.Width * 0.36); //当前值 cellWidth[2] = (float)(pageSize.Width * 0.2); //出厂值 cellWidth[3] = (float)(pageSize.Width * 0.1176); //计算列的起始位置 cellLeft[0] = e.PageSettings.Margins.Left; cellLeft[1] = cellLeft[0] + cellWidth[0]; cellLeft[2] = cellLeft[1] + cellWidth[1]; cellLeft[3] = cellLeft[2] + cellWidth[2]; //高度 int tempTop = e.MarginBounds.Top; //是否新的页面 bool tempIsNewPage = true; //设置打印字符串的格式 StringFormat tempStrFormat = new StringFormat { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center, Trimming = StringTrimming.EllipsisCharacter }; //设置字体 Font printFont = new Font("宋体", 9); //计算字体的高度 int fontHeight = (int)e.Graphics.MeasureString("KK00.10序号", printFont).Height; //指定高质量、低速度呈现 e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; try { string printStr; while(printPoint //判断当前打印是否超出页面范围,决定是否换页 //打印页脚 DrawFooter(e, PageNo); PageNo++; //继续分页打印 e.HasMorePages = true; return; } //打印当前页的内容 //KK00.00 printStr = saveTable.Rows[printPoint][0].ToString().Substring(5); if (printStr.Equals("00") || tempIsNewPage) {//一组数据的开始 tempIsNewPage = false; tempTop += 2; //绘制标题 DrawTitle(e, tempTop, tempStrFormat); tempTop += fontHeight; } //绘制内容 DrawContent(e, printPoint, tempTop, tempStrFormat); //更新Y轴高度 tempTop += fontHeight; //序号自增 printPoint++; //判断是否已经到终点 if(printPoint >= saveTable.Rows.Count) { //绘制页脚 DrawFooter(e, PageNo); //重置打印参数 PageNo = 1; printPoint = 0; return; } } } catch { } } /// /// 绘制页脚 /// /// 绘图对象 /// 页面序号 private void DrawFooter(System.Drawing.Printing.PrintPageEventArgs e, int pageNo) { Font font = new Font("微软雅黑", 10); //绘制直线 e.Graphics.DrawLine(new Pen(Color.Black, 1), new Point(e.MarginBounds.Left, e.MarginBounds.Bottom), new Point(e.MarginBounds.Right, e.MarginBounds.Bottom)); //公司信息标注 string tempStr = "Test for Windows(C) by 唠嗑一夏 Electric Corporation"; e.Graphics.DrawString(tempStr, font, Brushes.Black, e.MarginBounds.Left, e.MarginBounds.Bottom+2); //页脚序号 tempStr = pageNo.ToString(); e.Graphics.DrawString(tempStr, font, Brushes.Black, e.MarginBounds.Right - e.Graphics.MeasureString(tempStr, font).Width, e.MarginBounds.Bottom+2); } /// /// 绘制标题头 /// /// 绘图对象 /// Y轴坐标 /// 字符串格式 private void DrawTitle(System.Drawing.Printing.PrintPageEventArgs e, int tempTop, StringFormat tempFormat) { //绘制水平线 e.Graphics.DrawLine(Pens.Black, new Point(e.MarginBounds.Left, tempTop), new Point(e.MarginBounds.Right, tempTop)); Font printFont = new Font(fontName, fontNum); //计算字体的高度 K00ARk, 根据使用到的字进行组合成串 int fontHeight = (int)(e.Graphics.MeasureString("K00ARk", printFont).Height); //画刷 SolidBrush brush = new SolidBrush(Color.Black); //填充背景色 e.Graphics.FillRectangle(Brushes.LightBlue, new RectangleF(e.MarginBounds.Left, tempTop, e.MarginBounds.Width, fontHeight)); //列的序号 int col = 0; //列 序号 string drawString = TitleStr[col]; //矩形框 RectangleF rectangle = new RectangleF((int)cellLeft[col], tempTop, (int)cellWidth[col], fontHeight); e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 名称 drawString = TitleStr[col]; //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 设定值 drawString = TitleStr[col]; //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 默认值 drawString = TitleStr[col]; //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); } /// /// 绘制内容 /// /// 绘图对象 /// 数据行索引 /// Y轴坐标 /// 字符串格式 private void DrawContent(System.Drawing.Printing.PrintPageEventArgs e, int printIndex, int tempTop, StringFormat tempFormat) { Font printFont = new Font(fontName, fontNum); //计算字体的高度 K00ARk, 根据使用到的字进行组合成串 int fontHeight = (int)(e.Graphics.MeasureString("K00ARk", printFont).Height); //画刷 SolidBrush brush = new SolidBrush(Color.Black); //列的序号 int col = 0; //列 序号 string drawString = saveTable.Rows[printIndex][0].ToString() + saveTable.Rows[printIndex][1].ToString(); //矩形框 RectangleF rectangle = new RectangleF((int)cellLeft[col], tempTop, (int)cellWidth[col], fontHeight); e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 名称 drawString = saveTable.Rows[printIndex][3].ToString(); //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 设定值 drawString = saveTable.Rows[printIndex][2].ToString(); //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); col++; //列 默认值 drawString = saveTable.Rows[printIndex][4].ToString(); //水平向右平移 并设置矩形框的宽度 rectangle.X = cellLeft[col]; rectangle.Width = cellWidth[col]; e.Graphics.DrawString(drawString, printFont, brush, rectangle, tempFormat); } } }

最后的效果图 在这里插入图片描述 在这里插入图片描述

小节

1 使用PrintPreviewDialog + PrintDocument 可以实现打印预览功能

2 页面的绘制是在PrintDocument 的PrintDocument.PrintPage打印页事件中绘制

3 System.Drawing.Printing.PrintPageEventArgs e 在 e.Graphics的画布上进行绘制,DrawString绘制文本,DrawLine绘制直线,FillRectangle填充背景色,根据实际需要选择相应的接口。

4 绘制需要注意绘制点的X Y 坐标,可以以页面的边距e.MarginBounds作为参考点,使用e.Graphics.MeasureString可以测量该字符串占用的高和宽。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有