C# 打印功能:使用自定义表格绘制类

C# 打印功能:使用自定义表格绘制类

编码文章call10242025-02-18 10:38:5615A+A-

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

关键类及其组成部分

1.TableDocument 类

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

public class TableDocument
{
    public List Columns { get; set; } = new List(); // 表格列信息
    public List Rows { get; set; } = new List(); // 表格行信息
    public List Positions { get; set; } = new List(); // 单元格位置索引
    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 类

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

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 类

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

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

Column 类

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

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

使用示例

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

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);
    }
}

做一个码单

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));
        }
    }
}

总结

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

点击这里复制本文地址 以上内容由文彬编程网整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!
qrcode

文彬编程网 © All Rights Reserved.  蜀ICP备2024111239号-4