I am trying to implement print functionality on one of my project but I am not so good in this kind of work.
I already have connected with my thermal printer and write/print same samples. Now I am trying to find some way to design my receipt to look like receipt from attached image.
I have some ideas but I am not sure if they are good for this kind of work, one of them is to try to format my receipt in html and their render html like bitmap(image) and then print it, I already tried this but it looks like I have an loss of quality.
If somebody have any other ideas about how I can make receipt look like on from the image please share this info with me I will be very thankful.
This is what I already did to print some samples, for formatting I used graphics.DrawString
but I don't think that I can accomplish too much using it.
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);
}
In the past when doing this I split up the receipt into separate parts that used different fonts or alignments such as Header, Body, Footer.
I used the following class layout to encapsulate my printed text definition. (where you get the Font from and how you manage its lifetime is up to you)
public class PrintText
{
public PrintText(string text, Font font) : this(text, font, new StringFormat()) {}
public PrintText(string text, Font font, StringFormat stringFormat)
{
Text = text;
Font = font;
StringFormat = stringFormat;
}
public string Text { get; set; }
public Font Font { get; set; }
/// <summary> Default is horizontal string formatting </summary>
public StringFormat StringFormat { get; set; }
}
When there are longer lists of texts using the same font & padding then using a stringbuilder to build up your text makes life easy so you get a visual of how it will look just from inspecting your code.
If you had static text you can fit it all together as so:
var sb = new StringBuilder();
sb.AppendLine("Start of receipt");
sb.AppendLine("================");
sb.AppendLine("Item 1");
sb.AppendLine("Item 2");
sb.AppendLine("================");
Or if the data is a bit dynamic pass in some object you can iterate over and append your formatted text:
private class ReceiptItem
{
public string Name { get; set; }
public decimal Cost { get; set; }
public int Amount { get; set; }
public int Discount { get; set; }
public decimal Total { get { return Cost * Amount; } }
}
const int FIRST_COL_PAD = 20;
const int SECOND_COL_PAD = 7;
const int THIRD_COL_PAD = 20;
var sb = new StringBuilder();
sb.AppendLine("Start of receipt");
sb.AppendLine("================");
foreach (var item in receiptItems)
{
sb.Append(item.Name.PadRight(FIRST_COL_PAD));
var breakDown = item.Amount > 0 ? item.Amount + "x" + item.Cost : string.Empty;
sb.Append(breakDown.PadRight(SECOND_COL_PAD));
sb.AppendLine(string.Format("{0:0.00} A", item.Total).PadLeft(THIRD_COL_PAD));
if (item.Discount > 0)
{
sb.Append(string.Format("DISCOUNT {0:D2}%", item.Discount).PadRight(FIRST_COL_PAD + SECOND_COL_PAD));
sb.Append(string.Format("{0:0.00} A", -(item.Total / 100 * item.Discount)).PadLeft(THIRD_COL_PAD));
sb.AppendLine();
}
}
sb.AppendLine("================");
The output will look like:
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
================
Using the PrintText class earlier we can store our nicely formatted string builder output
var printText = new PrintText(sb.ToString(), new Font("Monospace Please...", 8));
Then finally use that when attempting to draw the string
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);
You can also play around with a few different graphical tweaks if the text doesn't print quite right such as:
g.SmoothingMode = SmoothingMode.AntiAlias;
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
I have designed a simple and smooth receipt design, i hope it will help you.
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);
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With