编辑
2025-02-03
C# 应用
00
请注意,本文编写于 92 天前,最后修改于 92 天前,其中某些信息可能已经过时。

目录

关键类及其组成部分
1.TableDocument 类
2. 辅助类
Position 类
Row 类
Column 类
使用示例
做一个码单
总结

在C#中进行打印功能时,我们可以通过使用System.Drawing和其他相关的库来创建自定义的打印内容。本篇文章将介绍一个由TableDocument类组成的自定义表格绘制方案,并展示如何使用该类进行各种操作,如绘图、绘制条码、绘制二维码、绘制文本等。

关键类及其组成部分

1.TableDocument

TableDocument类是实现打印功能的核心。它包含了表格列的宽度、行的高度、单元格的合并以及在单元格中绘制图像、文本和条码等功能。

C#
public class TableDocument { public List<Column> Columns { get; set; } = new List<Column>(); // 表格列信息 public List<Row> Rows { get; set; } = new List<Row>(); // 表格行信息 public List<Position> Positions { get; set; } = new List<Position>(); // 单元格位置索引 public Dictionary<(int, int), (int, int)> MergeCell { get; set; } = new Dictionary<(int, int), (int, int)>(); // 合并单元格信息 // 确定特定单元格的位置 public Position? GetPosition(int rowIndex, int columnIndex) { return Positions.Find(x => x.RowIndex == rowIndex && x.ColumnIndex == columnIndex); } // 获取列宽 public int GetColumnWidth(int columnIndex) { return Columns[columnIndex].Width; } // 获取行高 public int GetRowHeight(int rowIndex) { return Rows[rowIndex].Height; } // 绘制基本表格结构 public void Draw(Graphics graphics, int startX, int startY) { Pen pen = new Pen(Color.Black, 1); // 设置表格线条颜色和宽度 int currentY = startY; for (int i = 0; i < this.Rows.Count; i++) { int currentX = startX; for (int j = 0; j < this.Columns.Count; j++) { this.Positions.Add(new Position(i, j, new Point(currentX, currentY))); graphics.DrawRectangle(pen, currentX, currentY, this.Columns[j].Width, this.Rows[i].Height); currentX += this.Columns[j].Width; } currentY += this.Rows[i].Height; } // 处理单元格合并 foreach (var item in this.MergeCell) { int startRowIndex = item.Key.Item1; int startColIndex = item.Key.Item2; int w = 0; int h = 0; for (int i = startRowIndex; i <= item.Value.Item1; i++) { h += this.GetRowHeight(i); } for (int i = startColIndex; i <= item.Value.Item2; i++) { w += this.GetColumnWidth(i); } graphics.FillRectangle(new SolidBrush(System.Drawing.Color.White), this.GetPosition(startRowIndex, startColIndex).Point.X, this.GetPosition(startRowIndex, startColIndex).Point.Y, w, h); graphics.DrawRectangle(pen, this.GetPosition(startRowIndex, startColIndex).Point.X, this.GetPosition(startRowIndex, startColIndex).Point.Y, w, h); } } // 在指定单元格内绘制图像 public void DrawImageInCell(Graphics graphics, Position position, System.Drawing.Image image, Point offset) { Rectangle imageRect = new Rectangle(position.Point.X + offset.X, position.Point.Y + offset.Y, image.Width, image.Height); graphics.DrawImage(image, imageRect); } // 调整图像尺寸 private System.Drawing.Image ResizeImage(System.Drawing.Image image, double scaleFactor) { int newWidth = (int)(image.Width * scaleFactor); int newHeight = (int)(image.Height * scaleFactor); Bitmap resizedImage = new Bitmap(newWidth, newHeight); using (Graphics graphics = Graphics.FromImage(resizedImage)) { graphics.DrawImage(image, 0, 0, newWidth, newHeight); } return resizedImage; } // 在指定单元格内绘制二维码 public void DrawQRCode(Graphics graphics, string code, Position position, Point offset, int size = 3, double factor = 1) { var data = new QRCodeGenerator().CreateQrCode(code, QRCodeGenerator.ECCLevel.H); QRCode qcode = new QRCode(data); var img = qcode.GetGraphic(size); if (factor != 1) { var simg = ResizeImage(img, factor); this.DrawImageInCell(graphics, position, simg, offset); } else { this.DrawImageInCell(graphics, position, img, offset); } } // 在指定单元格内绘制条形码 public void Draw128Code(Graphics graphics, string code, Position position, int width, int height, Point offset, bool PureBarcode = false) { BarcodeWriter writer = new BarcodeWriter(); writer.Options = new ZXing.Common.EncodingOptions { Width = width, Height = height, Margin = 0, PureBarcode = PureBarcode }; writer.Format = BarcodeFormat.CODE_128; Bitmap bitmap2 = writer.Write(code); this.DrawImageInCell(graphics, position, bitmap2, offset); } // 在指定单元格内绘制文本 public void DrawTextInCell(Graphics graphics, Position position, string text, Font font, Brush brush, int mergeRow = 0, int mergeColumn = 0, StringFormat stringFormat = null, bool specialHeight = false) { StringFormat sf = StringFormat.GenericTypographic; SizeF sizeF1 = graphics.MeasureString(text, font, PointF.Empty, sf); SizeF sizeF = MeasureTextSize(graphics, text, font); RectangleF layoutRectangle; int rectHeight = this.GetRowHeight(position.RowIndex); for (int i = 0; i < mergeRow; i++) { rectHeight += this.GetRowHeight(position.RowIndex + i); } int rectWidth = this.GetColumnWidth(position.ColumnIndex); for (int i = 1; i < mergeColumn; i++) { rectWidth += this.GetColumnWidth(position.ColumnIndex + i); } if (specialHeight) { layoutRectangle = new RectangleF(position.Point.X, position.Point.Y - sizeF.Height / 2, rectWidth, rectHeight); } else { layoutRectangle = new RectangleF(position.Point.X, position.Point.Y, rectWidth, rectHeight); } if (stringFormat == null) { stringFormat = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center, }; } graphics.DrawString(text, font, brush, layoutRectangle, stringFormat); } // 测量文本的尺寸 public static SizeF MeasureTextSize(Graphics graphics, string text, Font font) { return graphics.MeasureString(text, font); } // 调整图像尺寸 public System.Drawing.Image ResizeImage(System.Drawing.Image image, int width, int height) { Bitmap resizedImage = new Bitmap(width, height); using (Graphics graphics = Graphics.FromImage(resizedImage)) { graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; graphics.DrawImage(image, new Rectangle(0, 0, width, height)); } return resizedImage; } }

2. 辅助类

Position

此类用于保存单元格的位置信息。

C#
public class Position { public int RowIndex { get; set; } = 0; public int ColumnIndex { get; set; } = 0; public Point Point { get; set; } public Position(int rowIndex, int columnIndex, Point point) { RowIndex = rowIndex; ColumnIndex = columnIndex; Point = point; } }

Row

用于保存每个表格行的高度。

C#
public class Row { public Row() { } public Row(int height) { this.Height = height; } public int Height { get; set; } = 0; }

Column

用于保存每个表格列的宽度。

C#
public class Column { public Column() { } public Column(int width) { this.Width = width; } public int Width { get; set; } = 0; }

使用示例

下面是一个使用TableDocument类进行打印的简单示例:

C#
private void PrintButton_Click(object sender, EventArgs e) { PrintDocument printDocument = new PrintDocument(); printDocument.PrintPage += new PrintPageEventHandler(PrintDocument_PrintPage); printDocument.Print(); } private void PrintDocument_PrintPage(object sender, PrintPageEventArgs ev) { TableDocument tableDoc = new TableDocument(); // 添加列 tableDoc.Columns.Add(new Column(100)); tableDoc.Columns.Add(new Column(200)); // 添加行 tableDoc.Rows.Add(new Row(50)); tableDoc.Rows.Add(new Row(100)); // 绘制表格 tableDoc.Draw(ev.Graphics, 10, 10); // 在单元格内绘制文本 Position pos = tableDoc.GetPosition(0, 0); if (pos != null) { tableDoc.DrawTextInCell(ev.Graphics, pos, "Hello, World!", new Font("Arial", 12), Brushes.Black); } }

image.png

做一个码单

C#
using System.Drawing.Printing; using static System.Windows.Forms.AxHost; namespace NPrinter { public partial class Form1 : Form { private PrintDocument printDocument = new PrintDocument(); TableDocument table = new TableDocument(); public Form1() { InitializeComponent(); } private void btnPrint1_Click(object sender, EventArgs e) { PrintDocument printDocument = new PrintDocument(); printDocument.PrintPage += new PrintPageEventHandler(PrintDocument_PrintPage); printDocument.Print(); } private void PrintDocument_PrintPage(object sender, PrintPageEventArgs e) { //读取数据集 Graphics graphics = e.Graphics; Pen pen = new Pen(Color.Black, 1); // 设置表格线条颜色和宽度 // 表格的起始位置 int startX = 10; int startY = 10; //设置行高 for (int i = 0; i < 8; i++) { table.Rows.Add(new Row(35)); // 设置行高 } //设置列宽 for (int i = 0; i < 4; i++) { table.Columns.Add(new Column(80)); // 设置列宽 } table.Columns[0].Width = 85; table.Columns[1].Width = 150; table.Columns[2].Width = 80; table.Columns[2].Width = 50; table.Rows[7].Height = 60; #region "设置合并" table.MergeCell.Add((0, 0), (0, 3)); //零头卷料信息卡 table.MergeCell.Add((1, 1), (1, 3)); //项目 table.MergeCell.Add((2, 1), (2, 3)); //批号 table.MergeCell.Add((3, 1), (3, 3)); //反番号 table.MergeCell.Add((4, 1), (4, 3)); //卷料零件号 table.MergeCell.Add((7, 0), (7, 3)); //条码 table.MergeCell.Add((6, 2), (6, 3)); //用户 table.MergeCell.Add((1, 3), (2, 3));//二维码 #endregion table.Draw(graphics, startX, startY); table.DrawTextInCell(graphics, table.GetPosition(0, 0), "零头卷料信息卡", new Font("SimHei", 12, FontStyle.Bold), Brushes.Black, 0, 4); table.DrawTextInCell(graphics, table.GetPosition(1, 0), "项目", new Font("SimHei", 8), Brushes.Black); table.DrawTextInCell(graphics, table.GetPosition(2, 0), "批号", new Font("SimHei", 8), Brushes.Black); table.DrawTextInCell(graphics, table.GetPosition(3, 0), "反番号", new Font("SimHei", 8), Brushes.Black); table.DrawTextInCell(graphics, table.GetPosition(4, 0), "卷料零件号", new Font("SimHei", 8), Brushes.Black); table.DrawTextInCell(graphics, table.GetPosition(5, 0), "退料长度", new Font("SimHei", 8), Brushes.Black); table.DrawTextInCell(graphics, table.GetPosition(6, 0), "退料日期/员工", new Font("SimHei", 8), Brushes.Black); table.DrawTextInCell(graphics, table.GetPosition(5, 2), "毛向", new Font("SimHei", 8), Brushes.Black); ////打印内容 table.DrawTextInCell(graphics, table.GetPosition(1, 1), "V254", new Font("Arial", 8), Brushes.Black, 0, 3, new StringFormat() { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }); table.DrawTextInCell(graphics, table.GetPosition(2, 1), "B20301", new Font("Arial", 8), Brushes.Black, 0, 3, new StringFormat() { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }); table.DrawTextInCell(graphics, table.GetPosition(3, 1), "", new Font("Arial", 8), Brushes.Black, 0, 3, new StringFormat() { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }); table.DrawTextInCell(graphics, table.GetPosition(4, 1), "5519982-8W51", new Font("Arial", 8), Brushes.Black, 0, 3, new StringFormat() { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }); table.DrawTextInCell(graphics, table.GetPosition(5, 1), "20.8", new Font("Arial", 10), Brushes.Black, 0, 3, new StringFormat() { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }); table.DrawTextInCell(graphics, table.GetPosition(6, 1), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), new Font("Arial", 10), Brushes.Black, 0, 0, new StringFormat() { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }); table.DrawTextInCell(graphics, table.GetPosition(5, 3), "A", new Font("Arial", 8), Brushes.Black); table.DrawTextInCell(graphics, table.GetPosition(6, 2), "张三", new Font("Arial", 8), Brushes.Black, 0, 2); table.DrawQRCode(graphics, "A000001", table.GetPosition(1, 3), new Point(10, 5), 3); ////生成条码 int w = 0; int h = 0; w = table.Columns.Take(4).Sum(x => x.Width) - 5; h = table.Rows[7].Height - 10; table.Draw128Code(graphics, "A000001", table.GetPosition(7, 0), w, h, new Point(3, 3)); } } }

image.png

总结

本文展示了一个自定义表格绘制类的实现及其使用方法,涵盖了绘制基表格、图像、条形码、二维码和文本的功能。通过这些方法,开发者可以灵活地进行C#打印功能的开发,为各种打印需求提供解决方案。

本文作者:rick

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!