用 C# 向打印机发送 ESC 命令

发布于 2024-09-01 13:46:32 字数 452 浏览 7 评论 0原文

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

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

我尝试做这样的事情:

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

        MyBigString.Insert(10, formFeed);

Whith this, the line 10 will do a FormFeed,但这不起作用

注意:我发送 MybigString一次全部发送到打印机。

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

感谢您的帮助。

PS:抱歉,我的英语不好,我是一名巴西开发者,还不会说英语。

My application needs to print invoices, then a get the invoice from database, insert information on the invoice in a big string (telling the line, column, etc.) after this I have the string ready to be sent to a printer.

My problem is: I need to put some ESC/P commands/characters in my big string

I tried to do something like this:

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

        MyBigString.Insert(10, formFeed);

Whith this, the line 10 will do a FormFeed, but this doesn't work

NOTE: I send the MybigString all at once to the printer.

To make my code works, I need to send the data line by line to a printer?

Thanks for the help.

PS: Sorry, for my English, I'am a Brazilian developer which don't speak English (yet).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

救赎№ 2024-09-08 13:46:32

在必须自己做之后,我之前已经在博客中谈到了这一点。 不要自吹自擂太大声,但我建议您阅读该条目,因为我谈论的是一个复杂的问题打印机的图像命令。如果你能理解这一点,你就可以打印任何东西!

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

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

请注意,不要使用 Write(string) 重载 < code>BinaryWriter 因为它会将字符串的长度作为字节添加到流中,这不是您想要的。 (我也在同一个项目上以艰难的方式了解到这一点后,也在博客上讨论了这一点。)

然后我使用一些代码来发送 byte 数组,从 BinaryWriter 获得,通过 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();
    }
}

祝你好运!

I've blogged about this before after having to do it myself. Not to toot my own horn too loudly, but I recommend that you read that entry, as I talk about a complex image command with the printer. If you can understand that, you can print anything!

(I talk about ESC/POS, used in retail receipt printers, but the semantics of the discussion applies to ESC/P, the older dot-matrix language, as well.)

In short, use a BinaryWriter instead of a string or you'll get hopelessly confused (as I did) as certain characters get "baked" in the wrong encoding on their way to the printer. (Trust me on this one! Do not use a StringBuilder when trying to talk in ESC/POS.)

Be careful not to use the Write(string) overload of the BinaryWriter as it will prepend the length of the string as a byte in the stream, which is not what you want. (I also blogged about that after learning that the hard way, too, on the same project.)

Then I use some code to send the byte array, as obtained from the BinaryWriter, directly to the printer by 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();
    }
}

Good luck!

涙—继续流 2024-09-08 13:46:32

绕过打印机驱动程序并使用其本机命令语言直接控制打印机是受支持的方案。 P/Invoke 在此 KB 中得到了很好的解释文章

您确定要这样做吗?温和地说,这种情况并不常见,通常仅尝试使用低成本销售点热敏打印机或点阵打印机。如果您不喜欢 PrintDocument.PrintPage 的机制,没有人喜欢,您可以考虑我的代码 此线程。请注意 FormFeed 方法。

Bypassing the printer driver and controlling the printer directly, using its native command language, is a supported scenario. The P/Invoke is explained well in this KB article.

Sure you want to do this? It is uncommon, to put it mildly, usually only attempted with low-cost Point-Of-Sale thermal or matrix printers. If you don't like the mechanics of PrintDocument.PrintPage, nobody does, you could consider my code in this thread. Note the FormFeed method.

小傻瓜 2024-09-08 13:46:32

“....OpenPrinter(printerName.Normalize(), out PrinterHandle, IntPtr.Zero)...”

可能也需要将 IntPtr.Zero 设置为原始。

打印机,特别是针式打印机,可以直接使用DOS、CMD方式进行打印,更加简单快捷,也可以使用基本的ESC/0x1b命令码来控制打印机。 。等

如windowos/graphic,通过设置openprinter(,,printer_defaults)printer_defaults和doc-inf可以是图形和原始,请参考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=text,......@

2=text.....

在第二页是

3=text.......

希望这可以有所帮助,祝你好运。

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

might needed to set IntPtr.Zero to raw too.

Printers, especially dot matrix, it can be direct using DOS, CMD method, which much simplest and faster for printing also can using basic ESC/0x1b command codes to controll the printer,. . etc.

as windowos/graphic, it can be graphics and raw by setting openprinter(,,printer_defaults) printer_defaults and doc-inf, pls refer win32 sdk references.

for any raw printing it can uses ESC command (refer to printer manual details) to print any graphic as what windows
driver did.

as printing raw, it just append any of the first 20 ascii, such as oxoc(formfeed) 0x0doa(0x0a, 0x0d, \n or newline)
each printer has slight ESC commands differences but using the master ESC command is fined for most of Dot matrix similar.

as raw mode example follows,
FormFeed , \n & \r

char cFormfeed=0x0c; // or \f

char cStr[]="1=text,......@\n2=text.....\r\f3=text......."; //use \f not using cFormfeed you can work it out

cStr > lpt1; //output to printer dos or cmd method, of cause must get the lpt1 available.

print out will be

first page

1=text,......@

2=text.....

at 2nd page is

3=text.......

hope this can be help, good luck.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文