Форматирование квитанции с помощью приложения WinForms

Я работаю с программным обеспечением для печати счетов в ресторане.

Я разработал квитанцию. но на самом деле они не похожи на квитанцию.

Я следовал решению от codeProject. Вот мой код создания квитанции:

//Get the Graphics object
        Graphics g = printTextEvArgs.Graphics;

        //Create a font Arial with size 16
        Font font = new Font("Arial", 10);
        float fontHeight = font.GetHeight();
        string underLine = "------------------------------------------";

        int startX = 10;
        int startY = 10;
        int offset = 40;

        //Create a solid brush with black color
        SolidBrush brush = new SolidBrush(Color.Black);
        if (RecieptType == "ktcprinter")
        {
        }
        else if (RecieptType == "billprinter")
        {
            g.DrawString(restaurantInfo.name, new Font("Courier New", 16), new SolidBrush(Color.Black), startX, startY);
            offset = offset + (int)fontHeight + 20;

            var wc = new WebClient();
            Image imgFromUrl = Image.FromStream(wc.OpenRead(b.restaurant_info.logo));
            g.DrawImage(imgFromUrl, 60, 40, 150, 100);

            offset = offset + (int)fontHeight + 50;

            g.DrawString("Address: " + restaurantInfo.address, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Phone: " + restaurantInfo.phone, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Vat Reg. No.: " + restaurantInfo.vat_reg_no, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Served By: " + employeeInfo.served_by, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + 13;
            g.DrawString(underLine, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + 13;

            foreach (var item in b.items)
            {
                string menuTitle = item.menu_title + item.quantity + item.price;
                g.DrawString(menuTitle, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
                offset = offset + (int)fontHeight + 5;
            }

            //Get UnderLine
            offset = offset - 8;
            g.DrawString(underLine, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + 15;

            g.DrawString("Sub Total: " + calculation.sub_total, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Discount: " + calculation.discount, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;                
            g.DrawString("Vat: " + calculation.vat, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Service Charge: " + calculation.service_charge, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Delivery Charge: " + calculation.delivery_charge, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);

            //Get UnderLine
            offset = offset + 12;
            g.DrawString(underLine, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + 12;

            g.DrawString("Total: " + calculation.total.PadRight(30), new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;

            //Get UnderLine
            offset = offset - 11;
            g.DrawString(underLine, new Font("Courier New", 12), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + 13;


            foreach (var item in b.payments)
            {
                string paymentMethod = item.method + item.amount;
                g.DrawString(paymentMethod, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
                offset = offset + (int)fontHeight + 5;
            }

            g.DrawString("Change: " + calculation.change, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            g.DrawString("Pay Tip: " + calculation.pay_tip, new Font("Courier New", 10), new SolidBrush(Color.Black), startX, startY + offset);
            offset = offset + (int)fontHeight + 5;
            offset = offset + 20;

            //offset = offset + 20;
            //g.DrawString("Total To Pay".PadRight(30) + string.Format("{0:c}"), variable, font, new SolidBrush(Color.Black), startX, startY + offset);
        }

        //Draw "Hello Printer!";
        //new Rectangle(margin X, margin Y, Width, Height)
        //g.DrawString(printString.ToString(),
        //font, brush, new Rectangle(5, 0, 350, 500));
    }

То, что я получил, похоже на изображение ниже. Я хочу, чтобы это было похоже на настоящую квитанцию.

Количество должно быть в столбце, а цена в другом столбце.

(Обратите внимание, что решение, которому я следовал, отлично сработало для них.)

Мой вывод на данный момент:

введите здесь описание изображения


person Onick Ahmed    schedule 29.01.2017    source источник
comment
Чтобы создать столбцы, вам просто нужно напечатать различные элементы в фиксированных позициях x на одной строке. Или: поскольку вы используете фиксированный шрифт, вы также можете заполнить левую часть пробелами до определенного количества символов. - Также: я предлагаю, когда вы спрашиваете о форматировании, приложить немного больше усилий для форматирования вашего вопроса!   -  person TaW    schedule 29.01.2017


Ответы (1)


Если вы хотите использовать фиксированный шрифт, например Courier или Consolas, вашу проблему можно легко решить, дополнив левую часть каждой строки до определенной длины пробелами.

Следующий шаг — заполнить правую часть, чтобы числа были выровнены по правому краю.

Для этого лучше всего написать небольшую вспомогательную функцию:

string alignedNumber(decimal number, int length)
{
    return ("$" + number).PadLeft(length, ' ');
}

Итак, вы пишете:

 g.DrawString("Change: ".PadRight(25, ' ') + alignedNumber(price, 8)...);

.. для всего вашего вывода со столбцами. (Выберите свои номера!)

Если вы решите перейти на пропорциональный шрифт, вам нужно будет написать отдельные вызовы DrawString для позиции и установить x-смещение для каждого. Для правильного выравнивания вам также нужно будет измерить ширину числовых строк, используя Graphics.MeasureString. См. здесь для примера

person TaW    schedule 29.01.2017
comment
Спасибо брат. Это работает отлично. есть еще одна вещь, которую я хотел знать. Я добавляю PadRight в предположительный заголовок меню. если menuTitle пересекает размер панели, будут ли дополнительные слова в новой строке? - person Onick Ahmed; 30.01.2017
comment
Нет. По умолчанию все, что вы нарисуете таким образом, соскользнет с планшета и потеряется. Вы можете подсчитать символы (для фиксированного шрифта) и разделить данные на две строки или использовать один из Перегрузка DrawString, которая принимает ограничивающий прямоугольник. Используйте Graphics.MeasureString для измерения перед рисованием, чтобы вы знали результирующую высоту!!! - Если вы довольны ответом, рассмотрите возможность его принятия..! - person TaW; 30.01.2017
comment
Извини, брат, я не знал процесса принятия. Теперь я принял ответ, так как это мне очень помогло. Кстати, брат, если есть какой-либо учебник или что-то еще для разделения данных на две строки, которые могли бы помочь мне, пожалуйста, предложите мне. Я буду очень благодарен. и, конечно же, сэр, если этот вопрос полезен, пожалуйста, проголосуйте за него. и еще раз спасибо - person Onick Ahmed; 30.01.2017
comment
Ну а разбить строку на слова можно было бы с помощью метода Split, если слова разделены одним разделителем. Более сложными и мощными являются регулярные выражения со словом param. Но, возможно, рисунок в центре рамки — это самый простой способ для заголовка. В ссылке на MSDN есть пример, который должен помочь; добавить в примеры для MeasureString и вы должны ладить. Необходимо знать размер бумаги в пикселях, то есть как физический размер, так и разрешение в dpi! - person TaW; 30.01.2017