C# POS应用开发-收据打印

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13390313/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 08:23:07  来源:igfitidea点击:

POS Application Development - Receipt Printing

c#wpfprintingepsonreceipt

提问by Nuno

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.

我一直在为餐厅/酒吧构建 POS 应用程序。
设计部分已经完成,在过去的一个月里我一直在编码。
一切正常,除了现在我需要打印。我必须打印到连接到运行该软件的计算机的收据打印机,然后我将尝试在像厨房打印机这样的远程打印机上打印。

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#.

我已经在这方面寻求帮助,结果发现在这些类型的打印机中打印的标准是使用 POS for .NET。问题是,这现在有点过时了,或者至少自几年以来它没有任何更新。关于如何使用这个库,有很多问题被问到,大多数答案都不太容易理解。因此,如果有人可以在收据打印机上逐步打印像一个简单的短语(“Hello World”),我将不胜感激。
我正在使用在 64 位 Windows 7 上运行的 Visual Studio 2012,我正在用 c# 编写 WPF。

采纳答案by Joe

POS for .NET is probably the way to go.

.NET 的 POS 可能是要走的路。

Most receipt printer manufacturers will provide an OPOS service object.

大多数收据打印机制造商都会提供 OPOS 服务对象。

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

作为这个MSDN文章指出,POS为.NET与OPOS V1.8服务对象是兼容的。

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.

OPOS / UPOS(.NET 的 POS 所基于的)恕我直言是一个设计糟糕的 API(由设备制造商而不是应用程序开发人员设计),但它是您今天拥有的最好的 API。

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.

我没有任何具体示例,但基础知识与 OPOS 相同 - 您需要打开、声明、启用设备,然后您可以调用其方法(例如打印)。您可以尝试查看 OPOS 示例,例如这个 PosPrinter1 示例,它可能与 .NET 的 POS 非常相似。

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

此博客提供了一些有关为 .NET 设置 POS 的信息,这些信息可能会有所帮助。

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

这是用于 OPOS 打印机的 VB Hello World。您首先需要创建一台打印机并将其添加到注册表中,并使用所需的逻辑设备名称 = LDN。我相信爱普生 ADK 包含一个实用程序,可以在注册表中添加打印机。此实用程序还可以对打印机执行健康检查以检查其安装是否正确。完成此操作后,将下面的代码调整为适用于 .NET 的 POS 应该很容易

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  

回答by nmaait

.NET Printing

.NET 打印

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

在 .NET 下打印并不太难。看看这里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.

打印到 POS/收据打印机将与打印到任何其他打印机相同,假设它是 Windows 打印机、网络或其他。如果您使用的是串行打印机,事情可能会稍微困难一些,因为您可能更需要使用制造商特定的 API,幸运的是,尽管现在操作系统完全支持大多数优秀的 POS 打印机。

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

首先,您需要在项目中添加对System.Printingdll的引用。

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.PrintVisualand define your document using xaml template.

您还可以利用PrintDialog.PrintVisual并使用 xaml 模板定义您的文档。

The print settings can be set using the PrintDialog properties.

可以使用 PrintDialog 属性设置打印设置。

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.

在大多数情况下,您真的不需要担心分页,打印机会在完成文档后自动切纸。

回答by devstuff

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.

看看 Michael Buen 对这个 SO question的回答,尤其是 UPDATE 位。

回答by Tim S

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.Printinglibraries. 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.

在花了很多时间处理 .Net 的 OPOS 和 POS 之后,我最终放弃了这些,只使用内置System.Drawing.Printing库。用于 .Net 的 OPOS 和 POS 最终开始工作起来很痛苦,并且最终没有像内置库那样工作。

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

我正在使用 Epson TM-T20II 收据打印机。

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. :)

希望它可以帮助某人跳过与自定义驱动程序有关的所有麻烦。:)