Ответ 1
В прошлом, когда я делал это, я делил квитанцию на отдельные части, которые использовали разные шрифты или выравнивания, такие как Header, Body, Footer.
Я использовал следующий макет класса, чтобы инкапсулировать мое определение текстового текста. (где вы получаете Шрифт и как вы управляете своей жизнью, зависит от вас)
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; }
}
Когда есть более длинные списки текстов с использованием одного и того же шрифта и отступов, то с помощью построителя строк для создания вашего текста упрощается жизнь, поэтому вы получите визуальное представление о том, как оно будет выглядеть только при проверке вашего кода.
Если у вас есть статический текст, вы можете поместить его все вместе так:
var sb = new StringBuilder();
sb.AppendLine("Start of receipt");
sb.AppendLine("================");
sb.AppendLine("Item 1");
sb.AppendLine("Item 2");
sb.AppendLine("================");
Или, если данные являются небольшим динамическим проходом в каком-либо объекте, вы можете перебирать и добавлять форматированный текст:
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("================");
Результат будет выглядеть так:
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;