Разработка POS-приложений — печать чеков

Я разрабатываю POS-приложение для ресторана/бара.
Часть дизайна завершена, и в течение последнего месяца я его программировал.
Все работает нормально, за исключением того, что мне нужно распечатать. Мне нужно печатать на чековом принтере, подключенном к компьютеру, на котором запущено программное обеспечение, а позже я попытаюсь распечатать на удаленном принтере, например на кухне.

Я искал помощи в этом вопросе только для того, чтобы обнаружить, что стандартом для печати на этих типах принтеров является использование POS для .NET. Дело в том, что сейчас это немного устарело или, по крайней мере, не было обновлений за пару лет. Задают много вопросов о том, как использовать эту библиотеку, и на большинство ответов не так-то просто ответить. Поэтому, если кто-нибудь может дать пошаговую помощь по печати простой фразы ("Hello World") на чековом принтере, я был бы очень признателен.
Я использую Visual Studio 2012, работающий на 64-битной Windows 7. и я кодирую WPF в С#.


person Nuno    schedule 15.11.2012    source источник
comment
В наши дни печать — это вопрос операционной системы... Прошли те времена, когда вам приходилось писать свой собственный драйвер (Боже, я скучаю по нему).   -  person lboshuizen    schedule 15.11.2012
comment
Что значит? Я действительно не понимаю ваш комментарий. POS-приложение разрабатывается каждый день, поэтому, очевидно, есть способы печати на чековом принтере.   -  person Nuno    schedule 15.11.2012
comment
Вы определились с принтером, который планируете использовать, потому что, скорее всего, вы будете использовать API производителя или программные драйверы?   -  person Mark Hall    schedule 15.11.2012
comment
Вот мое решение для печати на принтерах Star. Попробуйте поискать помощников для принтеров epson stackoverflow.com/questions/3108223/   -  person adopilot    schedule 15.11.2012
comment
Спасибо за ответы, я не думаю об использовании принтеров Epson, так как в моей стране они наиболее распространены.   -  person Nuno    schedule 15.11.2012
comment
Просто подумал, что хотел бы указать на то, что должно быть очевидным, но часто это не так: производители обычно хотят использовать их продукты, и поэтому они обычно будут рады указать вам правильное направление, если вы позвони им. Они не помогут вам с какими-либо специфическими проблемами приложения, но в целом могут предоставить вам информацию, необходимую для получения Hello World! распечатанный.   -  person Brandon Moore    schedule 25.01.2013


Ответы (4)


POS для .NET, вероятно, лучший вариант.

Большинство производителей чековых принтеров предоставляют сервисный объект OPOS.

И как указано в этой статье MSDN, POS для .NET совместим с сервисными объектами OPOS v1.8.

OPOS / UPOS (на котором основан POS для .NET) — это ИМХО плохо спроектированный API (разработанный производителями устройств, а не разработчиками приложений), но это лучшее, что у вас есть на сегодняшний день.

У меня нет конкретных примеров, но основы такие же, как у OPOS — вам нужно открыть, заявить, включить устройство, затем вы можете вызвать его методы (например, печать). Вы можете попробовать посмотреть образец OPOS, например этот образец PosPrinter1, который, вероятно, будет очень похож в POS для .NET.

Этот блог содержит некоторую информацию о настройке POS для .NET, которая может оказаться полезной.

ОБНОВЛЕНИЕ

Вот VB Hello World для принтера OPOS. Сначала нужно создать принтер и добавить его в реестр с требуемым именем логического устройства = LDN. Я считаю, что Epson ADK включает в себя утилиту для добавления принтера в реестр. Эта утилита также может выполнять проверку работоспособности принтера, чтобы убедиться, что он установлен правильно. После того, как вы это сделаете, будет достаточно легко адаптировать приведенный ниже код к POS для .NET.

OPOSPOSPrinter.Open "MyPrinter"    ' LDN of your printer   
OPOSPOSPrinter.Claim 500           ' Timeout   
OPOSPOSPrinter.DeviceEnabled = True  

'- Print   
OPOSPOSPrinter.PrintNormal 2, "Hello world"  

'- Close the printer   
If OPOSPOSPrinter.Claimed then   
   OPOSPOSPrinter.Release   
End If  
OPOSPOSPrinter.Close  
person Joe    schedule 15.11.2012
comment
Хорошо, поэтому я скачал Epson OPOS ADK, Common Control Objects и установил POS для .NET, но ни один из этих веб-сайтов не дает хорошей информации о прямом способе использования библиотек. Я знаю, что мне нужно добавить ссылку на Microdoft.PointOfService, но что мне делать дальше? Что делать с объектами управления связью OPOS? Первое, чему каждый учится, когда начинает программировать на языке, которого не знает, — это писать приложение «Hello World». Я думаю, это то, о чем должна говорить документация по OPOS или POS для .NET. Любая помощь по этому вопросу? - person Nuno; 15.11.2012
comment
Работает на 100%! Большое спасибо! - person Nuno; 15.11.2012
comment
@Nuno в .NET 4 у вас могут возникнуть проблемы, если вы хотите использовать динамические функции C # (для запуска POS для .NET в 4), и вы можете ограничить использование epson или другого известного принтера. Большинство дешевых принтеров не будут работать с POS для .NET! Из-за этого я отказался от POS.NET. - person GorillaApe; 09.12.2012
comment
@Parhs, вы можете вспомнить, что вы использовали вместо POS.NET? - person ingredient_15939; 20.06.2015

Я знаю, что это старый пост, но для тех, кто все еще ищет решение, я могу рассказать вам, что я сделал.

Потратив много часов на возню с OPOS и POS для .Net, я просто отказался от них и просто использовал встроенные библиотеки System.Drawing.Printing. OPOS и POS для .Net оказались трудными для работы и в конечном итоге не работали так же хорошо, как встроенные библиотеки.

Я использую чековый принтер Epson TM-T20II.

Вот некоторый код, который хорошо работал для меня.

public static void PrintReceiptForTransaction()
{
    PrintDocument recordDoc = new PrintDocument();

    recordDoc.DocumentName = "Customer Receipt";
    recordDoc.PrintPage += new PrintPageEventHandler(ReceiptPrinter.PrintReceiptPage); // function below
    recordDoc.PrintController = new StandardPrintController(); // hides status dialog popup
                                                                // Comment if debugging 
    PrinterSettings ps = new PrinterSettings();
    ps.PrinterName = "EPSON TM-T20II Receipt";
    recordDoc.PrinterSettings = ps;
    recordDoc.Print();
    // --------------------------------------

    // Uncomment if debugging - shows dialog instead
    //PrintPreviewDialog printPrvDlg = new PrintPreviewDialog();
    //printPrvDlg.Document = recordDoc;
    //printPrvDlg.Width = 1200;
    //printPrvDlg.Height = 800;
    //printPrvDlg.ShowDialog();
    // --------------------------------------

    recordDoc.Dispose();
}

private static void PrintReceiptPage(object sender, PrintPageEventArgs e)
{
    float x = 10;
    float y = 5;
    float width = 270.0F; // max width I found through trial and error
    float height = 0F;

    Font drawFontArial12Bold = new Font("Arial", 12, FontStyle.Bold);
    Font drawFontArial10Regular = new Font("Arial", 10, FontStyle.Regular);
    SolidBrush drawBrush = new SolidBrush(Color.Black);

    // Set format of string.
    StringFormat drawFormatCenter = new StringFormat();
    drawFormatCenter.Alignment = StringAlignment.Center;
    StringFormat drawFormatLeft = new StringFormat();
    drawFormatLeft.Alignment = StringAlignment.Near;
    StringFormat drawFormatRight = new StringFormat();
    drawFormatRight.Alignment = StringAlignment.Far;

    // Draw string to screen.
    string text = "Company Name";
    e.Graphics.DrawString(text, drawFontArial12Bold, drawBrush, new RectangleF(x, y, width, height), drawFormatCenter);
    y += e.Graphics.MeasureString(text, drawFontArial12Bold).Height;

    text = "Address";
    e.Graphics.DrawString(text, drawFontArial10Regular, drawBrush, new RectangleF(x, y, width, height), drawFormatCenter);
    y += e.Graphics.MeasureString(text, drawFontArial10Regular).Height;

    // ... and so on
}

Надеюсь, это поможет кому-то избежать возни с кастомными драйверами. :)

person Tim S    schedule 27.11.2014
comment
Гарантирует ли этот код возможность продолжения задания на печать вместо страницы 1 страницы 2? - person Bon; 27.04.2015
comment
Извините за «раскопки» такой старой темы, я решил попробовать ваше решение, и оно отлично работает после нескольких настроек (с SAM4S Ellix 20 II), однако оно всегда использует фиксированную длину бумаги (размер A4), независимо от того, как долго квитанция тратит много бумаги. Могу ли я спросить, знаете ли вы, как сделать длину динамической? Большое Вам спасибо - person molbal; 14.02.2016
comment
Хм, к сожалению, я вообще не помню, чтобы сталкивался с этой проблемой - кажется, она всегда обрезается после последних напечатанных строк. Извините, я не могу больше помочь. - person Tim S; 16.02.2016
comment
для 58 мм я обнаружил, что 190,0F - максимальная ширина. - person AiApaec; 28.02.2016
comment
Откуда вы получаете объект/функцию ReceiptPrinter.PrintReceiptPage? - person Articulous; 28.07.2016
comment
Таким образом, класс, в котором это находится, называется ReceiptPrinter, а ReceiptPrinter.PrintReceiptPage — это просто дескриптор статического метода в приведенном выше коде. Вы можете сослаться на PrintReceiptPage без имени класса, но это старый код, который я не использовал какое-то время, поэтому я не могу его попробовать. Удачи! - person Tim S; 29.07.2016
comment
Для тех, кто читает это и пробует впервые (например, я!), вам нужно будет добавить ссылку на System.Drawing.dll, так как именно здесь живут объекты PrintDocument и StandardPrintController. - person Brett Rigby; 02.02.2017
comment
@TimS, как передать динамические данные обработчику событий PrintReceiptPage? - person NuWin; 09.07.2017

Печать .NET

Печать под .NET не так уж сложна. Посмотрите здесь и на msdn.

Печать на принтере POS/чеков будет такой же, как печать на любом другом принтере, если это принтер Windows, сетевой или другой. Если вы используете последовательный принтер, все может быть немного сложнее, потому что вам, скорее всего, потребуется использовать API конкретного производителя, к счастью, хотя большинство хороших POS-принтеров в наши дни полностью поддерживаются ОС.

Во-первых, вам нужно будет добавить ссылку на System.Printing dll в ваш проект.

Тогда печать так же проста, как

private void PrintText(string text)
{
    var printDlg = new PrintDialog();
    var doc = new FlowDocument(new Paragraph(new Run(text)));
    doc.PagePadding = new Thickness(10);

    printDlg.PrintDocument((doc as IDocumentPaginatorSource).DocumentPaginator, "Print Caption");
}

Использовать..

PrintText("Hello World");

Вы также можете использовать PrintDialog.PrintVisual. и определите свой документ, используя шаблон xaml.

Параметры печати можно задать с помощью свойств PrintDialog.

Получение принтера, на котором вы хотите печатать

private PrintQueue FindPrinter(string printerName)
{
    var printers = new PrintServer().GetPrintQueues();
    foreach (var printer in printers)
    {
        if (printer.FullName == printerName)
        {
            return printer;
        }
    }
    return LocalPrintServer.GetDefaultPrintQueue();
}

Однако при печати на чековом принтере необходимо учитывать несколько моментов, связанных с форматированием. В частности, вам нужно будет учитывать ширину вашей страницы и количество символов, которые вы можете разместить в каждой строке; для меня это было много проб и ошибок, особенно с разными размерами шрифта.

В большинстве случаев вам не нужно беспокоиться о разбиении на страницы, принтер автоматически обрежет бумагу, когда закончит ваш документ.

person nmaait    schedule 15.11.2012
comment
Печать на POS/принтере чеков будет такой же, как печать на любом другом принтере — не делайте этого. Профессиональное POS-приложение должно отслеживать сигналы состояния от чекового принтера (например, низкий уровень бумаги, открытая крышка, замятие бумаги), которые недоступны при использовании драйвера принтера Windows. - person Joe; 15.11.2012
comment
А как насчет скорости? так как в этом случае я использую драйвер Windows (верно?), печать займет больше времени, верно? Если я хочу напечатать целую квитанцию ​​​​для стола, сколько времени, по вашему мнению, потребуется принтеру, чтобы закончить работу? - person Nuno; 15.11.2012
comment
@Джо, что ты тогда предлагаешь? - person Nuno; 15.11.2012
comment
@Joe То, что вы говорите, идеально, но большинство людей не заботятся об этих функциях, и если вы не предоставите свое оборудование, это нереально. - person GorillaApe; 09.12.2012
comment
на самом деле, я хотел бы использовать такой подход. Я попробую и дам вам знать об этом @nmaait - person swdev; 02.04.2013

Если вы хотите печатать на полной скорости принтера, вам, вероятно, потребуется использовать escape-коды для конкретного принтера и сгенерировать «сырой» вывод.

Взгляните на ответ Майкла Буэна на этот вопрос SO, особенно бит UPDATE.

person devstuff    schedule 15.11.2012
comment
Не используйте универсальный принтер, как это предлагается в связанном вопросе. Профессиональное POS-приложение должно отслеживать сигналы состояния от чекового принтера (например, низкий уровень бумаги, открытая крышка, замятие бумаги), которые недоступны при использовании обычного принтера. - person Joe; 15.11.2012
comment
@Джо, пожалуйста! Когда я говорю, что профессиональное POS-приложение захочет отслеживать сигналы состояния от чекового принтера (например, низкий уровень бумаги, открытая крышка, замятие бумаги), люди смеются надо мной и думают, что я умственно отсталый. Немногие приложения / люди заботятся об этом. Я тоже собираюсь задать вопрос - person GorillaApe; 27.11.2012