【问题标题】:Send ESC commands to a printer in C#在 C# 中向打印机发送 ESC 命令
【发布时间】:2011-02-19 17:38:36
【问题描述】:

我的应用程序需要打印发票,然后从数据库中获取发票,在发票上插入一个大字符串中的信息(告诉行、列等),然后我准备好将字符串发送到打印机.

我的问题是:我需要在我的大字符串中放入一些 ESC/P 命令/字符

我试图做这样的事情:

        char formFeed = (char)12;
        Convert.ToChar(12);

        MyBigString.Insert(10, formFeed);

这样,第 10 行将执行 FormFeed,但这不起作用

注意:我将 MybigString 一次性发送到打印机。

为了让我的代码正常工作,我需要将数据逐行发送到打印机吗?

感谢您的帮助。

PS:抱歉,对于我的英语,我是一名不会说英语的巴西开发人员(目前)。

【问题讨论】:

  • 打印机是EPSON FX-1170(点阵打印机)

标签: c# printing command epson


【解决方案1】:

I've blogged about this before after having to do it myself. 不要太大声地按喇叭,但我建议您阅读该条目,因为我谈到了打印机的复杂图像命令。如果你能理解,你可以打印任何东西!

(我说的是零售收据打印机中使用的 ESC/POS,但讨论的语义也适用于 ESC/P,旧的点阵语言。)

简而言之,请使用BinaryWriter 而不是string,否则您会感到非常困惑(就像我所做的那样),因为某些字符在进入打印机的途中会以错误的编码“烘烤”。 (相信我!不要在尝试使用 ESC/POS 通话时使用 StringBuilder。)

注意不要使用BinaryWriterWrite(string) 重载,因为它会将字符串的长度作为字节添加到流中,这不是您想要的。 (I also blogged about that 在同一个项目上也经历了艰难的学习。)

然后我使用一些代码将从BinaryWriter 获得的byte 数组通过P/Invoking 直接发送到打印机:

private static void Print(string printerName, byte[] document)
{
    NativeMethods.DOC_INFO_1 documentInfo;
    IntPtr printerHandle;

    documentInfo = new NativeMethods.DOC_INFO_1();
    documentInfo.pDataType = "RAW";
    documentInfo.pDocName = "Bit Image Test";

    printerHandle = new IntPtr(0);

    if (NativeMethods.OpenPrinter(printerName.Normalize(), out printerHandle, IntPtr.Zero))
    {
        if (NativeMethods.StartDocPrinter(printerHandle, 1, documentInfo))
        {
            int bytesWritten;
            byte[] managedData;
            IntPtr unmanagedData;

            managedData = document;
            unmanagedData = Marshal.AllocCoTaskMem(managedData.Length);
            Marshal.Copy(managedData, 0, unmanagedData, managedData.Length);

            if (NativeMethods.StartPagePrinter(printerHandle))
            {
                NativeMethods.WritePrinter(
                    printerHandle,
                    unmanagedData,
                    managedData.Length,
                    out bytesWritten);
                NativeMethods.EndPagePrinter(printerHandle);
            }
            else
            {
                throw new Win32Exception();
            }

            Marshal.FreeCoTaskMem(unmanagedData);

            NativeMethods.EndDocPrinter(printerHandle);
        }
        else
        {
            throw new Win32Exception();
        }

        NativeMethods.ClosePrinter(printerHandle);
    }
    else
    {
        throw new Win32Exception();
    }
}

祝你好运!

【讨论】:

  • 感谢 Nicholas,您的代码对我来说似乎很先进,但我正在努力理解它。 :D
  • @Nicholas 你的博客已经失效了。无论如何我可以看看那个代码吗?
【解决方案2】:

绕过打印机驱动程序并使用其本机命令语言直接控制打印机是受支持的方案。这个KB article很好地解释了P/Invoke。

确定要这样做吗?委婉地说,这种情况并不常见,通常只尝试使用低成本的销售点热敏打印机或矩阵打印机。如果你不喜欢 PrintDocument.PrintPage 的机制,没人喜欢,你可以考虑我在this thread 中的代码。注意 FormFeed 方法。

【讨论】:

  • 阅读并实施知识库文章,对我来说效果很好。谢谢
  • 知识库文章以“RAW”模式打开打印机,这意味着您应该发出打印机驱动程序将接受的字节。尝试将 0xFF 发送到 XPS 打印机将导致它什么也不做。您必须将模式更改为“TEXT”(social.msdn.microsoft.com/forums/en-US/windowsxps/thread/…
【解决方案3】:

"....OpenPrinter(printerName.Normalize(), out printerHandle, IntPtr.Zero)..."

可能还需要将 IntPtr.Zero 设置为 raw。

打印机,尤其是点阵打印机,可以直接使用DOS、CMD方式,打印更简单快捷,也可以使用基本的ESC/0x1b命令代码来控制打印机,。 .等等

作为windowos/graphic,通过设置openprinter(,,printer_defaults)和doc-inf可以是图形和raw,请参考win32 sdk参考。

对于任何原始打印,它可以使用 ESC 命令(请参阅打印机手册详细信息)将任何图形打印为什么窗口 司机做到了。

作为原始打印,它只是附加前 20 个 ascii 中的任何一个,例如 oxoc(formfeed) 0x0doa(0x0a, 0x0d, \n 或换行符) 每台打印机都有轻微的 ESC 命令差异,但对于大多数类似的点阵,使用主 ESC 命令会被罚款。

如下原始模式示例, 换页,\n & \r

char cFormfeed=0x0c; // 或 \f

char cStr[]="1=文本,......@\n2=文本.....\r\f3=文本......."; //使用 \f 不使用 cFormfeed 你可以解决它

cStr > lpt1; //输出到打印机 dos 或 cmd 方法,当然必须让 lpt1 可用。

打印出来会是

首页

1=文本,......@

2=文本.....

在第二页是

3=文本.......

希望对你有帮助,祝你好运。

【讨论】:

    猜你喜欢
    • 2020-04-04
    • 1970-01-01
    • 2020-11-16
    • 2015-08-20
    • 2015-02-18
    • 2019-01-27
    • 2017-10-21
    • 2016-04-28
    相关资源
    最近更新 更多