Posts

The Exciting World of Receipt Printing

While the title is partially tongue-in-cheek, in that Printing Receipts would generally not be a particularly exciting topic, it still offers it’s own unique challenges. Like many other purposes, The programmatic Printing of receipts actually has a lot of libraries, conventions, and legacy. While it’s surely not as exciting and hardly get’s the coverage of libraries like OpenGL or Direct3D, I think that sort of thing that makes it an ideal topic for a blog post.

The primary challenge when it comes to printing receipts at all is abstraction of the hardware itself. On a Windows system, this can be solved by accessing the Receipt Printer device as you do any other Printer. What you can do from there is use your desired Reporting Tool- Crystal Reports, Jasper reports, etc to do what you want. In my case I used Jasper. For Jasper Reports, there is something of a caveat;In the implementation we were using, we were using Jasper Report’s internal JRViewer control and using that ti display the report. This worked well. However, in adding support for two different compiled Jasper Files (one for a normal printer, one for receipt printers) we encounter the issue that we cannot control what the JRViewer does; if you launch it with a report, that is what it will print if you press the print button.

What are our options?

So close yet so far away- with that one thing missing a goal is within our grasp. How do we conquer this? A good understanding of Java helps. In this specific case the JRViewer control of Jasper Reports was part of our own Java application which we had been using to interface between our C# components and Jasper Reports. To me, the solution seemed almost trivial after some thought- Java has reflection- so we could just examine the internals of the JRViewer control, and redirect the print button to our own Action Listener. This had some drawbacks (in particular, code changes to the JRViewer could break the reflection code), But it worked for our purposes. Observe:

By using reflection, we are able to take control over the JRViewer control and completely redirect click events on the Print button to our own code, which can perform the same logic of the normal Print button but with our added logic for selecting the appropriate report to use (both reports are generated and turned into a JasperPrint based on whether a printer selected is determined to be a receipt printer).

This has a bit of a disadvantage, however, since it requires the POS device to be available as a standard Windows Printer. I’m not convinced this can be considered a guarantee. But what choice do we have?

Introducing Microsoft Point of Service for .NET

As it turns out- and to the surprise of none of us- the task of printing receipts in a general, abstract fashion- without having to custom-code for every possible POS Printer- has been a requirement of countless other companies and individuals for a long time. Microsoft even has a Library designed almost specifically for this service, known as “Microsoft Point of Service for .NET” in fact, the library itself has many parallels to things such as DirectX. It doesn’t completely solve the problem- we still have to manage things involving formats, text, and so forth, but it presents the means by which we can do this.

I’m still learning a lot about it myself, so I can’t really provide anything particularly useful in terms of C# Code. (At least, not yet!). My current approach is to take the hardware abstraction provided by the Library and expand it to create a “Printer agnostic” capability, such that programs can specify what they would like, what can be sacrificed, and so forth, and the Library does what it can using the POS library. In order to use a Printer with the POS library, it needs to be registered and available through OPOS. Every receipt Printer software I was able to download appears to register it’s device for use via OPOS- in fact some of their software provided only that capability, with no Windows Driver- thus the need for this approach since the first one would never work for those.

Once it is functioning and we’ve got it into our own products, I will see if I can make it generic and share it here. Fundamentally what we are building appears to be a “PML” (Printer Management Layer) we are provided a hardware agnostic API which can provide us information such as how fast the printer is, how many characters per line, how wide is the paper, can it print colour or bitmaps? both? etc. and the task is to present as many capabilities as possible to any applications while degrading gracefully when applications want to say print in colour but cannot.