在C#中进行打印功能时,我们可以通过使用System.Drawing
和其他相关的库来创建自定义的打印内容。本篇文章将介绍一个由TableDocument
类组成的自定义表格绘制方案,并展示如何使用该类进行各种操作,如绘图、绘制条码、绘制二维码、绘制文本等。
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;
}
}
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);
}
}
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));
}
}
}
本文展示了一个自定义表格绘制类的实现及其使用方法,涵盖了绘制基表格、图像、条形码、二维码和文本的功能。通过这些方法,开发者可以灵活地进行C#打印功能的开发,为各种打印需求提供解决方案。
本文作者:rick
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!