Windows:如何告诉打印机在打印过程中发出换页?

发布于 2024-10-09 11:22:24 字数 6224 浏览 0 评论 0原文

我需要告诉打印机驱动程序发出换页符。

我使用以下方式直接打印到打印机:

设置API 调用。

很多灵感来自KB138594 - HOWTO:使用 Win32 API 将原始数据发送到打印机< /a>.该知识库文章中需要注意的重要一点是,它们(以及我复制的代码)以 RAW 模式启动文档:

// Fill in the structure with info about this "document."
docInfo.pDocName = "My Document";
docInfo.pOutputFile = NULL;
docInfo.pDatatype = "RAW";
StartDocPrinter(hPrinter, 1, docInfo);

注意: RAW 模式(与 TEXT 模式相反)意味着我们向打印机驱动程序发出原始字节。我们承诺用它能理解的语言进行交谈。

然后,我们可以使用 WritePrinter 写入我们想要的所有内容:

WritePrinter(hPrinter, "Hello, world!"); //note, extra parameters removed for clarity
WritePrinter(hPrinter, 0x0c); //form-feed

这里的问题是 0x0c 换页字符。因为我们已在 RAW 模式下打开打印机,所以我们承诺将发送它可以处理的打印机驱动程序字节。 大多数打印机的驱动程序采用0x0C表示您想要发出换页。

问题在于其他打印机(PDF 打印机Microsoft XPS 打印机)期望 RAW 打印作业采用其自己的打印机语言。如果您使用上述方法打印到 XPS 或 PDF 打印机:什么也不会发生(即没有保存对话框,没有打印任何内容)。

请求解决方案不久前这个问题,得到的答复是你必须将文档模式从 RAW: 更改

docInfo.pDatatype = "RAW";

TEXT:

docInfo.pDataType = "TEXT";

这可能是因为你发送了 “RAW”数据直接发送到打印机, RAW 可以是任何 PDL。但XPS 司机可能只会明白 XPS,它可能会忽略 你的“未知:你好,世界!0xFF”PDL。这 XPS 驱动程序可能(如果有的话)仅 写入时接受 XPS 数据 直接到它。

如果您想在 XPS 上渲染文本 驱动程序,你应该使用GDI。你可能会 能够将纯文本发送到 如果您指定“TEXT”作为驱动程序 数据类型。附带的打印处理器 然后驱动程序将“转换” 通过渲染作业为您提供纯文本 通过 GDI 到驱动程序。

这样就成功了,我更改了代码,将打印文档声明为 TEXT

// Fill in the structure with info about this "document."
docInfo.pDocName = "My Document";
docInfo.pOutputFile = NULL;
docInfo.pDatatype = "TEXT";
StartDocPrinter(hPrinter, 1, docInfo);
WritePrinter(hPrinter, "Hello, world!");
WritePrinter(hPrinter, 0x0c); //form-feed

然后出现 XPS 和 PDF 打印机的另存为对话框,并且保存正确。我以为一切都已解决。

除了几个月后,当我尝试打印到real打印机:换页不会发生 - 大概是因为我不再以“原始打印机命令”模式进行打印。

所以我需要的是Windows-ish发出换页的方式。我需要 API 调用来告诉打印机驱动程序我希望打印机执行换页操作。

我的问题:如何告诉打印机在打印过程中发出换页?


数据类型背景

打印处理器告诉后台处理程序更改作业根据文档数据类型。它与打印机驱动程序结合使用,将假脱机打印作业从硬盘发送到打印机。

软件供应商有时会开发自己的打印处理器来支持自定义数据类型。通常,打印处理器不需要管理员进行任何设置或干预。

数据类型

Windows 打印过程通常支持五种数据类型。增强型图元文件 (EMF) 和准备打印 (RAW) 这两种最常用的数据类型会以不同的方式影响客户端计算机和打印服务器计算机的性能。

RAW 是除基于 Windows 的程序之外的客户端的默认数据类型。 RAW 数据类型告诉假脱机程序在打印之前根本不要更改打印作业。对于这种数据类型,准备打印作业的整个过程都在客户端计算机上完成。

EMF(或增强型图元文件)是大多数基于 Windows 的程序的默认数据类型。使用 EMF,打印的文档将更改为比 RAW 文件更便携的图元文件格式,并且通常可以在任何打印机上打印。 EMF 文件往往比包含相同打印作业的 RAW 文件小。关于性能,只有打印作业的第一部分被更改或在客户端计算机上呈现,但大部分影响发生在打印服务器计算机上,这也有助于客户端计算机上的应用程序更快地将控制权返回给用户。

下表(摘自 MSDN)显示了五种不同的数据类型默认 Windows 打印处理器支持:

数据类型RAW
后台处理程序说明:打印不做任何更改的文档。
使用:这是所有不基于 Windows 的客户端的数据类型。

数据类型RAW [附加 FF]
后台处理程序说明:附加换页符 (0x0C),但不进行其他更改。 (如果没有尾随换页,PCL 打印机会忽略文档的最后一页。)
使用:某些应用程序需要。 Windows 不会分配它,但可以在“打印处理器”对话框中将其设置为默认值。

数据类型RAW [FF auto]
后台处理程序说明:检查尾随换页符,如果尚不存在则添加一个,但不进行其他更改。
使用:某些应用程序需要。 Windows 不会分配它,但可以在“打印处理器”对话框中将其设置为默认值。

数据类型NT EMF 1.00x
后台打印程序说明:将文档视为增强型图元文件 (EMF),而不是打印机驱动程序输出的 RAW 数据。
使用:EMF 文档由 Windows 创建。

数据类型文本
后台打印程序说明:将整个作业视为 ANSI 文本,并使用打印设备的出厂默认设置添加打印规范。 使用:当打印作业是简单文本并且目标打印设备无法解释简单文本时,这非常有用。

您可以通过控制面板中打印机的属性查看打印机可用的打印处理器以及每个处理器支持的数据类型:

alt text

另请参阅

i need to tell a printer driver to issue a form feed.

i'm printing directly to a printer using the:

set of API calls.

A lot of the inspiration came from KB138594 - HOWTO: Send Raw Data to a Printer by Using the Win32 API. An important point to note in that KB article is that they (and my copied code) start the document in RAW mode:

// Fill in the structure with info about this "document."
docInfo.pDocName = "My Document";
docInfo.pOutputFile = NULL;
docInfo.pDatatype = "RAW";
StartDocPrinter(hPrinter, 1, docInfo);

Note: RAW mode (as opposed to TEXT mode) means we are issuing raw bytes to the printer driver. We promise to talk in the language it understands.

We can then use WritePrinter to write everything we want:

WritePrinter(hPrinter, "Hello, world!"); //note, extra parameters removed for clarity
WritePrinter(hPrinter, 0x0c); //form-feed

The problem here is the 0x0c form-feed character. Because we've opened the printer in RAW mode, we are promising we will send the printer driver bytes it can process. The drivers of most printers take 0x0C to mean you want to issue a form-feed.

The problem is that other printers (PDF printer, Microsoft XPS Printers) expect RAW print jobs to be in their own printer language. If you use the above to print to an XPS or PDF printer: nothing happens (i.e. no save dialog, nothing printed).

i asked for a solution to this question a while ago, and a response was that you have to change the document mode from RAW:

docInfo.pDatatype = "RAW";

to TEXT:

docInfo.pDataType = "TEXT";

Well this probably is because you send
"RAW" data directly to the printer,
and RAW can be any PDL. But the XPS
driver will probably only understands
XPS, and it will probably just ignore
your "unknown: Hello, world!0xFF" PDL. The
XPS driver will probably, if any, only
accept XPS data when you write
directly to it.

If you want to render text on the XPS
driver, you should use GDI. You might
be able to send plain text to the
driver if you specify "TEXT" as the
datatype. The print processor attached
to the driver will then "convert" the
plaintext for you by rendering the job
via GDI to the driver.

So that worked, i changed my code to declare the print document as TEXT:

// Fill in the structure with info about this "document."
docInfo.pDocName = "My Document";
docInfo.pOutputFile = NULL;
docInfo.pDatatype = "TEXT";
StartDocPrinter(hPrinter, 1, docInfo);
WritePrinter(hPrinter, "Hello, world!");
WritePrinter(hPrinter, 0x0c); //form-feed

And then the Save As dialog for XPS and PDF printers appear, and it saves correctly. And i thought all was fixed.

Except months later, when i tried to print to a <quote>real</quote> printer: the form-feed doesn't happen - presumably because i am no longer printing in "raw printer commands" mode.

So what i need is the Windows-ish way of issuing a form feed. i need the API call that will tell printer driver that i want the printer to perform a form-feed.

My question: How to tell a printer to issue a Form-Feed during printing?


Background on Data Types

The print processor tells the spooler to alter a job according to the document data type. It works in conjunction with the printer driver to send the spooled print jobs from the hard drive to the printer.

Software vendors occasionally develop their own print processors to support custom data types. Normally, the print processor does not require any settings or intervention from administrators.

Data types

The Windows printing process normally supports five data types. The two most commonly used data types, enhanced metafile (EMF) and ready to print (RAW), affect performance in different ways on both the client computer and the print server computer.

RAW is the default data type for clients other than Windows-based programs. The RAW data type tells the spooler not to alter the print job at all prior to printing. With this data type, the entire process of preparing the print job is done on the client computer.

EMF, or enhanced metafile, is the default datatype with most Windows-based programs. With EMF, the printed document is altered into a metafile format that is more portable than RAW files and usually can be printed on any printer. EMF files tend to be smaller than RAW files that contain the same print job. Regarding performance, only the first portion of a print job is altered, or rendered on the client computer, but most of the impact is on the print server computer, which also helps the application on the client computer to return control to the user faster.

The following table (taken from MSDN) shows the five different data types supported by the default Windows print processor:

Data type: RAW
Directions to spooler: Print the document with no changes.
Use: This is the data type for all clients not based on Windows.

Data type: RAW [FF appended]
Directions to spooler: Append a form-feed character (0x0C), but make no other changes. (A PCL printer omits the document's last page if there is no trailing form-feed.)
Use: Required for some applications. Windows does not assign it, but it can be set as the default in the Print Processor dialog box.

Data type: RAW [FF auto]
Directions to spooler: Check for a trailing form-feed and add one if it is not already there, but make no other changes.
Use: Required for some applications. Windows does not assign it, but it can be set as the default in the Print Processor dialog box.

Data type: NT EMF 1.00x
Directions to spooler: Treat the document as an enhanced metafile (EMF) rather than the RAW data that the printer driver puts out.
Use: EMF documents are created by Windows.

Data type: TEXT
Directions to spooler: Treat the entire job as ANSI text and add print specifications using the print device's factory defaults.
Use: This is useful when the print job is simple text and the target print device cannot interpret simple text.

You can see the print processors available for a printer, and the data types that each processor supports, through the properties of a printer in the control panel:

alt text

See also

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

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

发布评论

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

评论(3

不爱素颜 2024-10-16 11:22:24

是的,那行不通。您故意绕过打印机驱动程序,即为任何打印机提供通用接口的代码块。这让您需要处理每种特定打印机型号的特殊性。

有一些通用的接口,您在代码中使用的接口是旧点阵打印机使用的接口。 PCL 在惠普激光打印机上很常见。 Postscript 在高端打印机上很常见。后两者有自己的换页符。

然后是廉价激光和喷墨打印机的海洋。他们通常根本没有明确定义的界面。它们没有在打印机内部安装处理器将打印机命令转换为纸张上的点,而是让打印机驱动程序完成所有艰苦的工作。你永远不会得到其中之一,该接口是专有的且没有文档记录。

打印机驱动程序是您的朋友。 PrintDocument 使用它的类。获取换页很简单,只需设置 e.HasMorePages = true 并退出PrintPage 事件处理程序。您已经看到了我链接的 StreamPrinter 类。

Yeah, that doesn't work. You are intentionally bypassing the printer driver, the chunk of code that presents a universal interface to any printer. Which leaves you to deal with the peculiarities of each specific printer model.

There are some common interfaces, the one you used in your code is the one that dot matrix printers of old used. PCL is common on Hewlett Packard laser printers. Postscript is common on high-end printers. The latter two have their own incantations to get a form feed.

Then there's the ocean of cheap laser and ink jet printers. They often don't have a well defined interface at all. Instead of having a processor inside the printer that translates printer commands to dots on paper, they let the printer driver do all the hard work. You'll never get one of those going, the interface is proprietary and undocumented.

The printer driver is your friend here. PrintDocument the class to use it. Getting a form feed is easy, just set e.HasMorePages = true and exit the PrintPage event handler. You already saw the StreamPrinter class I linked.

不如归去 2024-10-16 11:22:24

我不熟悉 TEXT 文档类型,但我认为它只是最低公分母“哑打印机”表示形式。如果是这样,它可能会识别换页字符,除非您使用了错误的字符 - 它不是 0x120xFF,而是 0x0c >。请参阅http://en.wikipedia.org/wiki/Ascii

I'm unfamiliar with the TEXT document type, but I presume it's just a lowest common denominator "dumb printer" representation. If so, it might recognize a form-feed character, except you've been using the wrong character - it's not 0x12 or 0xFF, it's 0x0c. See http://en.wikipedia.org/wiki/Ascii

人生戏 2024-10-16 11:22:24

由于我上次的回答没有帮助,让我们尝试一下显而易见的方法。您是否尝试过在需要分页符时先执行 EndPagePrinter ,然后再执行 StartPagePrinter

如果这仍然不起作用,您可能需要使用 GDI 来实现这一点。该堆栈看起来与您正在使用的堆栈略有不同:

  • CreateDC
  • CreateFont
  • SelectObject
  • StartDoc
    • 起始页
      • 文本输出
    • 结束页
  • EndDoc
  • DeleteDC

您需要管理字体并将文本放置在自己在页面的每一行位置。

Since my last answer was no help, lets try the obvious. Have you tried doing EndPagePrinter followed by StartPagePrinter whenever you need a page break?

If that still doesn't work you may need to do it the hard way, using GDI. The stack looks just slightly different from the one you're using:

  • CreateDC
  • CreateFont
  • SelectObject
  • StartDoc
    • StartPage
      • TextOut
    • EndPage
  • EndDoc
  • DeleteDC

You'll be required to manage a font and place the text on the page yourself at each line position.

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