用C#WPF书写精美收据,以便在热敏打印机POS上打印
我试图在我的一个项目上实现打印功能,但我在这方面的工作做得不太好 我已经连接了热敏打印机,并编写/打印了相同的样本。 现在我正试图找到一些方法来设计我的收据,使之看起来像附件中的收据 我有一些想法,但我不确定它们是否适合这类工作,其中之一是尝试将我的收据格式化为html格式,并将其呈现为类似于位图(图像)的html格式,然后将其打印出来,我已经尝试过这一点,但看起来我的质量有所下降 如果有人对我如何使收据看起来像图片上的其他想法,请与我共享此信息,我将非常感谢 这是我在打印一些示例时所做的,我使用了用C#WPF书写精美收据,以便在热敏打印机POS上打印,c#,wpf,printing,C#,Wpf,Printing,我试图在我的一个项目上实现打印功能,但我在这方面的工作做得不太好 我已经连接了热敏打印机,并编写/打印了相同的样本。 现在我正试图找到一些方法来设计我的收据,使之看起来像附件中的收据 我有一些想法,但我不确定它们是否适合这类工作,其中之一是尝试将我的收据格式化为html格式,并将其呈现为类似于位图(图像)的html格式,然后将其打印出来,我已经尝试过这一点,但看起来我的质量有所下降 如果有人对我如何使收据看起来像图片上的其他想法,请与我共享此信息,我将非常感谢 这是我在打印一些示例时所做的,我使
graphics.DrawString
进行格式化,但我认为我不能用它完成太多的工作
public void Print()
{
var doc = new PrintDocument();
doc.PrintPage += new PrintPageEventHandler(ProvideContent);
doc.Print();
}
public void ProvideContent(object sender, PrintPageEventArgs e)
{
Graphics graphics = e.Graphics;
Font font = new Font("Courier New", 10);
float fontHeight = font.GetHeight();
int startX = 0;
int startY = 0;
int Offset = 20;
e.PageSettings.PaperSize.Width = 50;
graphics.DrawString("Welcome to MSST", new Font("Courier New", 8),
new SolidBrush(Color.Black), startX, startY + Offset);
Offset = Offset + 20;
graphics.DrawString("Ticket No:" + "4525554654545",
new Font("Courier New", 14),
new SolidBrush(Color.Black), startX, startY + Offset);
Offset = Offset + 20;
graphics.DrawString("Ticket Date :" + "21/12/215",
new Font("Courier New", 14),
new SolidBrush(Color.Black), startX, startY + Offset);
Offset = Offset + 20;
String underLine = "------------------------------------------";
graphics.DrawString(underLine, new Font("Courier New", 14),
new SolidBrush(Color.Black), startX, startY + Offset);
Offset = Offset + 20;
String Grosstotal = "Total Amount to Pay = " + "2566";
Offset = Offset + 20;
underLine = "------------------------------------------";
graphics.DrawString(underLine, new Font("Courier New", 14),
new SolidBrush(Color.Black), startX, startY + Offset);
Offset = Offset + 20;
graphics.DrawString(Grosstotal, new Font("Courier New", 14),
new SolidBrush(Color.Black), startX, startY + Offset);
}
我假设您不是在热敏打印机上打印输出,而是在普通的高分辨率位图打印机上打印输出?如果是这样的话,您的问题基本上需要生成位图/pdf或其他图形描述,然后发送到打印机。由于您提供的示例图像仅包含文本,因此您的任务只是使用坐标和字体大小来布局文本。然而,你将面临的问题是寻找正确的字体,并获得绝对正确的间距和字距等。这将是我的出发点。看看你是否能找到一种与图片中的字体相似的字体。在photoshop/gimp或类似软件中进行测试。将termal打印的照片设置为背景层,然后查看是否可以使前景保持相同。一旦你可以复制到那里,就去完成软件。从photoshop模型中选择文本坐标 在过去,当我这样做时,我会将收据分成不同的部分,使用不同的字体或对齐方式,如页眉、正文、页脚 我使用下面的类布局来封装我的打印文本定义。 (字体的来源和使用寿命由您决定)
公共类PrintText
{
公共打印文本(字符串文本,字体):此(文本,字体,新StringFormat()){}
公共打印文本(字符串文本、字体、字符串格式)
{
文本=文本;
字体=字体;
StringFormat=StringFormat;
}
公共字符串文本{get;set;}
公共字体{get;set;}
///默认设置为水平字符串格式
公共StringFormat StringFormat{get;set;}
}
当有较长的文本列表使用相同的字体和填充时,使用stringbuilder来构建文本会使您的生活变得简单,这样您就可以通过查看代码来直观地了解文本的外观
如果您有静态文本,则可以将其组合在一起:
var sb=new StringBuilder();
sb.附加行(“收货开始”);
某人加上一行(“===============================”);
sb.附录行(“第1项”);
sb.附录行(“第2项”);
某人加上一行(“===============================”);
或者,如果数据在某个对象中是位动态传递,则可以迭代并附加格式化文本:
私有类ReceiptItem
{
公共字符串名称{get;set;}
公共十进制成本{get;set;}
公共整数金额{get;set;}
公共整数折扣{get;set;}
公共十进制总数{get{返回成本*金额;}}
}
const int FIRST\u COL\u PAD=20;
第二列的常数=7;
第三列的常数=20;
var sb=新的StringBuilder();
sb.附加行(“收货开始”);
某人加上一行(“===============================”);
foreach(收据项目中的var项目)
{
sb.追加(项目名称PadRight(第一栏));
var细分=项目。金额>0?项目。金额+“x”+项目。成本:字符串。空;
某人追加(分解PadRight(第二列PAD));
sb.AppendLine(string.Format(“{0:0.00}A”,item.Total.PadLeft(THIRD_COL_PAD));
如果(项目折扣>0)
{
sb.Append(string.Format(“折扣{0:D2}%”,item.DISCOUNT).PadRight(第一列+第二列));
sb.Append(string.Format(“{0:0.00}A”,-(item.Total/100*item.Discount)).PadLeft(THIRD_COL_PAD));
(某人);
}
}
某人加上一行(“===============================”);
输出将如下所示:
Start of receipt
================
Joes Food 1x10 10.00 A
DISCOUNT 10% -1.00 A
Fun Facts 1x20 20.00 A
DISCOUNT 15% -3.00 A
Bag of Sand 7x40 280.00 A
================
使用前面的PrintText类,我们可以存储格式良好的字符串生成器输出
var printText = new PrintText(sb.ToString(), new Font("Monospace Please...", 8));
最后,在尝试绘制字符串时使用它
var layoutArea = new SizeF(AvailableWidth, 0);
SizeF stringSize = g.MeasureString(printText.Text, printText.Font, layoutArea, printText.StringFormat);
RectangleF rectf = new RectangleF(new PointF(), new SizeF(AvailableWidth, stringSize.Height));
g.DrawString(printText.Text, printText.Font, Brushes.Black, rectf, printText.StringFormat);
如果文本打印不正确,您还可以使用一些不同的图形调整,例如:
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
您可以将收据转换为位图图像并使用XPSDocumentGenerator类。或者使用开源库,如MigraDocs,将其转换为PDF并发送到打印机我设计了一个简单而流畅的收据设计,希望它能对您有所帮助
public class PrintJob
{
private PrintDocument PrintDocument;
private Graphics graphics;
private Order order { set; get; }
private Shop shop { set; get; }
private int InitialHeight = 360;
public PrintJob(Order order, Shop shop)
{
this.order = order;
this.shop = shop;
AdjustHeight();
}
private void AdjustHeight()
{
var capacity = 5 * order.ItemTransactions.Capacity;
InitialHeight += capacity;
capacity = 5 * order.DealTransactions.Capacity;
InitialHeight += capacity;
}
public void Print(string printername)
{
PrintDocument = new PrintDocument();
PrintDocument.PrinterSettings.PrinterName = printername;
PrintDocument.PrintPage += new PrintPageEventHandler(FormatPage);
PrintDocument.Print();
}
void DrawAtStart(string text, int Offset)
{
int startX = 10;
int startY = 5;
Font minifont = new Font("Arial", 5);
graphics.DrawString(text, minifont,
new SolidBrush(Color.Black), startX + 5, startY + Offset);
}
void InsertItem(string key, string value, int Offset)
{
Font minifont = new Font("Arial", 5);
int startX = 10;
int startY = 5;
graphics.DrawString(key, minifont,
new SolidBrush(Color.Black), startX + 5, startY + Offset);
graphics.DrawString(value, minifont,
new SolidBrush(Color.Black), startX + 130, startY + Offset);
}
void InsertHeaderStyleItem(string key, string value, int Offset)
{
int startX = 10;
int startY = 5;
Font itemfont = new Font("Arial", 6, FontStyle.Bold);
graphics.DrawString(key, itemfont,
new SolidBrush(Color.Black), startX + 5, startY + Offset);
graphics.DrawString(value, itemfont,
new SolidBrush(Color.Black), startX + 130, startY + Offset);
}
void DrawLine(string text, Font font, int Offset, int xOffset)
{
int startX = 10;
int startY = 5;
graphics.DrawString(text, font,
new SolidBrush(Color.Black), startX + xOffset, startY + Offset);
}
void DrawSimpleString(string text, Font font, int Offset, int xOffset)
{
int startX = 10;
int startY = 5;
graphics.DrawString(text, font,
new SolidBrush(Color.Black), startX + xOffset, startY + Offset);
}
private void FormatPage(object sender, PrintPageEventArgs e)
{
graphics = e.Graphics;
Font minifont = new Font("Arial", 5);
Font itemfont = new Font("Arial", 6);
Font smallfont = new Font("Arial", 8);
Font mediumfont = new Font("Arial", 10);
Font largefont = new Font("Arial", 12);
int Offset = 10;
int smallinc = 10, mediuminc = 12, largeinc = 15;
//Image image = Resources.logo;
//e.Graphics.DrawImage(image, startX + 50, startY + Offset, 100, 30);
//graphics.DrawString("Welcome to HOT AND CRISPY", smallfont,
// new SolidBrush(Color.Black), startX + 22, startY + Offset);
Offset = Offset + largeinc + 10;
String underLine = "-------------------------------------";
DrawLine(underLine, largefont, Offset, 0);
Offset = Offset + mediuminc;
DrawAtStart("Invoice Number: " + order.Invoice, Offset);
if (!String.Equals(order.Customer.Address, "N/A"))
{
Offset = Offset + mediuminc;
DrawAtStart("Address: " + order.Customer.Address, Offset);
}
if (!String.Equals(order.Customer.Phone, "N/A"))
{
Offset = Offset + mediuminc;
DrawAtStart("Phone # : " + order.Customer.Phone, Offset);
}
Offset = Offset + mediuminc;
DrawAtStart("Date: " + order.Date, Offset);
Offset = Offset + smallinc;
underLine = "-------------------------";
DrawLine(underLine, largefont, Offset, 30);
Offset = Offset + largeinc;
InsertHeaderStyleItem("Name. ", "Price. ", Offset);
Offset = Offset + largeinc;
foreach (var itran in order.ItemTransactions)
{
InsertItem(itran.Item.Name + " x " + itran.Quantity, itran.Total.CValue, Offset);
Offset = Offset + smallinc;
}
foreach (var dtran in order.DealTransactions)
{
InsertItem(dtran.Deal.Name, dtran.Total.CValue, Offset);
Offset = Offset + smallinc;
foreach (var di in dtran.Deal.DealItems)
{
InsertItem(di.Item.Name + " x " + (dtran.Quantity * di.Quantity), "", Offset);
Offset = Offset + smallinc;
}
}
underLine = "-------------------------";
DrawLine(underLine, largefont, Offset, 30);
Offset = Offset + largeinc;
InsertItem(" Net. Total: ", order.Total.CValue, Offset);
if (!order.Cash.Discount.IsZero())
{
Offset = Offset + smallinc;
InsertItem(" Discount: ", order.Cash.Discount.CValue, Offset);
}
Offset = Offset + smallinc;
InsertHeaderStyleItem(" Amount Payable: ", order.GrossTotal.CValue, Offset);
Offset = Offset + largeinc;
String address = shop.Address;
DrawSimpleString("Address: " + address, minifont, Offset, 15);
Offset = Offset + smallinc;
String number = "Tel: " + shop.Phone1 + " - OR - " + shop.Phone2;
DrawSimpleString(number, minifont, Offset, 35);
Offset = Offset + 7;
underLine = "-------------------------------------";
DrawLine(underLine, largefont, Offset, 0);
Offset = Offset + mediuminc;
String greetings = "Thanks for visiting us.";
DrawSimpleString(greetings, mediumfont, Offset, 28);
Offset = Offset + mediuminc;
underLine = "-------------------------------------";
DrawLine(underLine, largefont, Offset, 0);
Offset += (2 * mediuminc);
string tip = "TIP: -----------------------------";
InsertItem(tip, "", Offset);
Offset = Offset + largeinc;
string DrawnBy = "Meganos Softwares: 0312-0459491 - OR - 0321-6228321";
DrawSimpleString(DrawnBy, minifont, Offset, 15);
}
}
由于我们的要求,一些用于添加图像的代码已经在这里进行了注释,您可以在标题处添加您的徽标,正如您在第二张图像中所看到的。
字体对我来说并不重要,我的目标是找到最好/最简单的方法为热敏打印机编写一个好的收件人,我遇到的问题是如何将文本格式化/排列到收件人中,比如设置纸张大小、将文本排列在纸张的左侧或右侧,等等……在您的示例中使用DrawString函数有什么问题?您在查找放置文本的正确坐标时遇到问题吗?如果是这样的话,我会尝试一下找出纸张的宽度,我认为这不是最好的方法,但如果你能证明我对此非常满意。回答这个问题可能需要一些时间,假设你只是打电话,你可以毫不费力地做到这一点。简而言之,您需要创建自己的DocumentPaginator。overrode print函数将为收据创建一个UserControl,您将打印控件的DataContext设置为某种ReceiptViewModel。令人惊讶的是,可以将生成的图像打印到收据打印机上吗?对不起,我在哪里可以下载Monosp