POS Application Development - Receipt Printing

74,921

Solution 1

POS for .NET is probably the way to go.

Most receipt printer manufacturers will provide an OPOS service object.

And as this MSDN article states, POS for .NET is compatible with OPOS v1.8 service objects.

OPOS / UPOS (on which POS for .NET is based) is IMHO a poorly-designed API (designed by device manufacturers rather than application developers), but it's the best you have today.

I don't have any specific samples but the basics are the same as OPOS - you need to Open, Claim, Enable a device, then you can call its methods (such as Print). You might try looking at an OPOS sample, for example this PosPrinter1 sample, which will probably be very similar to POS for .NET.

This blog has some information about setting up POS for .NET that might be helpful.

UPDATE

Here's a VB Hello World for an OPOS printer. You first need to create a printer and add it to the registry with the required Logical Device Name = LDN. I believe the Epson ADK includes a utility to add a printer in the registry. This utility can also perform a health check on the printer to check it is installed correctly. Once you've done this, it should be easy enough to adapt the code below to POS for .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  

Solution 2

I know this is an old post, but for those still looking for a solution, I can tell you what I did.

After spending many hours messing with OPOS and POS for .Net, I ended up just abandoning those and just using the built-in System.Drawing.Printing libraries. The OPOS and POS for .Net ended up being a pain to get working and ultimately didn't work as well as the built-in libraries.

I'm using an Epson TM-T20II receipt printer.

Here's some code that worked well for me.

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
}

Hopefully it helps someone skip all the messing around with custom drivers. :)

Solution 3

.NET Printing

Printing under .NET isn't too difficult. Take a look here and on msdn.

Printing to a POS / receipt printer will be the same as printing to any other printer, assuming it is a Windows printer, network or otherwise. If you are using a serial printer, things may be a little more difficult because you will more then likely need to use manufacturer specific API's, fortunately though most good POS printers these days are fully supported by the OS.

First, you will need to add a reference to System.Printing dll to your project.

Then printing is as simple as

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");
}

To use..

PrintText("Hello World");

You can also leverage the PrintDialog.PrintVisual and define your document using xaml template.

The print settings can be set using the PrintDialog properties.

Getting the printer you want to print to

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

A few things to keep in mind though when printing to a receipt printer, you will need to take into account formatting. More specifically you will need to consider the width of your page and how many characters you can fit on each line; this was a lot of trial and error for me, especially with different font sizes.

In most cases you don't really need to worry about paging, the printer will cut the paper automatically when it has completed your document.

Solution 4

If you want to print at the full speed of the printer, you will probably need to use printer-specific escape codes, and generate the "raw" output.

Have a look at Michael Buen's answer to this SO question, especially the UPDATE bit.

Share:
74,921
Nuno
Author by

Nuno

Updated on July 09, 2022

Comments

  • Nuno
    Nuno almost 2 years

    I've been building a POS application for a restaurant/bar.
    The design part is done and for the past month I've been coding it.
    Everything works fine except now I need to print. I have to print to a receipt printer connected to the computer running the software and later I'll try to print in a remote printer like a kitchen one.

    I've searched for help in the matter only to find that the standard for printing in these types of printers is using POS for .NET. The thing is, this is now a bit outdated or at least it hasn't had any updates since a couple of years. There's a lot of questions being asked on how to use this library and most of the answers aren't quite easy to follow. So if anybody could give a step by step help on printing like a simple phrase ("Hello World") on a receipt printer i would be very grateful.
    I'm using visual studio 2012 running on a 64 bit windows 7 and i'm coding WPF in c#.

    • lboshuizen
      lboshuizen over 11 years
      Printing is an OS matter these days... Gone are the days that you have to write your own driver (God I miss it).
    • Nuno
      Nuno over 11 years
      Which means? I dont really understand your comment.. POS app are beeing develloped every day so there obviously ways of printing to a receipt printer..
    • Mark Hall
      Mark Hall over 11 years
      Have you decided on a printer that you plan to use, because most likely you will be using the manufactureres API or software drivers
    • adopilot
      adopilot over 11 years
      Here is my my solution for printing with Star printers, You cold try searching helpers for epson printers stackoverflow.com/questions/3108223/…
    • Nuno
      Nuno over 11 years
      Thanks for the answers, i though of using epson printers since in my country they're the most common
    • Brandon Moore
      Brandon Moore over 11 years
      Just thought I'd point out what should be obvious but often isn't: The manufacturers generally want you to use their products and as such they will usually be glad to point you in the right direction if you call them. They won't help you with any application specific problems, but they can generally get you the info you need to get "Hello World!" printed out.
  • Joe
    Joe over 11 years
    Don't use a generic printer as suggested in the linked question. A professional POS application will want to monitor status signals from the receipt printer (e.g. paper low, cover open, paper jam), which are not available when using a generic printer.
  • Joe
    Joe over 11 years
    "Printing to a POS / reciept printer will be the same as printing to any other printer" - don't do this. A professional POS application will want to monitor status signals from the receipt printer (e.g. paper low, cover open, paper jam), which are not available when using a Windows printer driver.
  • Nuno
    Nuno over 11 years
    What about speed? since in this case i'm using the windows driver (right?) it will take longer to print right? If i want to print a whole receipt for a table how much time would you think it would take the printer to end?
  • Nuno
    Nuno over 11 years
    @Joe What do you suggest then?
  • Nuno
    Nuno over 11 years
    Okay so i downloaded Epson OPOS ADK, the Common Control Objects nad installed POS for .NET but none of these websites provide a good intel on straight forward way of using the libraries.. I know i have to add reference to Microdoft.PointOfService but what do i do next? What do i do with the OPOS commom control objects? The first thing everybody learns to do when they start coding with a language they dont know is wrting the 'Hello World' app.. I thinks this is something the documention on OPOS or POS for .NET should say Any help on this?
  • Nuno
    Nuno over 11 years
    Working 100% Thank you very much!
  • GorillaApe
    GorillaApe over 11 years
    @Joe please ! When I say "professional POS application will want to monitor status signals from the receipt printer (e.g. paper low, cover open, paper jam)" people make fun of me and think that i am a retard. Few apps/people care about these.I am going to open a question too
  • GorillaApe
    GorillaApe over 11 years
    @Nuno in .NET 4 you may have problems if you want to use dynamic features of C# (in order to run POS for .NET in 4) and you can limited using epson or other well known printer. Most cheap printers wont work with POS for .NET! I dropped POS.NET because of this.
  • GorillaApe
    GorillaApe over 11 years
    @Joe What you say it is ideal but most people dont care about these features and if you dont provide your hardware it is unrealistic.
  • swdev
    swdev about 11 years
    actually, I would like to use this kind of approach. I'll have a try and let you know about it @nmaait
  • Bon
    Bon about 9 years
    Does this code Guarantee that can do continues print job instead of page 1 page 2 thing?
  • ingredient_15939
    ingredient_15939 almost 9 years
    @Parhs, Can you recall what you ended up using instead of POS.NET?
  • molbal
    molbal over 8 years
    Sorry for 'excavating' such an old topic, I decided to try your solution and it works fine after a few tweasks (With a SAM4S Ellix 20 II) however it always uses up a fixed length of paper (A4 sized) no matter how long the receipt is wasting a lot of paper. May I ask if you know how to make the length dynamic? Thank you very much
  • Tim S
    Tim S over 8 years
    Hmm, unfortunately I don't remember running into that problem at all - it seems to always cut off after the last lines that were printed. Sorry I can't be of more help.
  • AiApaec
    AiApaec about 8 years
    for 58mm i've found 190.0F is the max width.
  • Articulous
    Articulous almost 8 years
    Where are you getting your ReceiptPrinter.PrintReceiptPage object/function from?
  • Tim S
    Tim S almost 8 years
    So the class that this is in is called "ReceiptPrinter", and "ReceiptPrinter.PrintReceiptPage" is just a handle to the static method in the code above. You may be able to reference the PrintReceiptPage without the class name, but this is old code that I haven't used for a while so I'm not able to try it. Good luck!
  • Brett Rigby
    Brett Rigby over 7 years
    For those that might be reading this and trying it out for the first time (like me!) then you'll need to add a reference to System.Drawing.dll, as this is where PrintDocument and StandardPrintController objects live.
  • NuWin
    NuWin almost 7 years
    @TimS how would I pass dynamic data to the PrintReceiptPage event handler?