14

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

我正在使用以下方法直接打印到打印机:

一组 API 调用。

很多灵感来自KB138594 - HOWTO: Send Raw Data to a Printer by Using the Win32 API。该知识库文章中需要注意的重要一点是,它们(和我复制的代码)以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 打印机的“另存为”对话框,并正确保存。我认为一切都已解决。

除了几个月后,当我尝试打印到 <quote>real</quote> 打印机时:换页没有发生 - 大概是因为我不再以“原始打印机命令”模式打印。

所以我需要的是Windows 式的发送表单的方式。我需要 API 调用来告诉打印机驱动程序我希望打印机执行换页。

我的问题:如何告诉打印机在打印过程中发出 Form-Feed?


数据类型背景

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

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

数据类型

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

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

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

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

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

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

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

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

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

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

替代文字

也可以看看

4

3 回答 3

4

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

有一些通用接口,您在代码中使用的接口是旧点阵打印机使用的接口。PCL 在 Hewlett Packard 激光打印机上很常见。Postscript 在高端打印机上很常见。后两者有自己的咒语来获取表单提要。

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

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

于 2010-12-30T19:59:02.727 回答
0

由于我的最后一个答案没有帮助,让我们试试显而易见的。您是否尝试过在需要分页符时执行EndPagePrinter后续操作?StartPagePrinter

如果这仍然不起作用,您可能需要使用 GDI 来做这件事。堆栈看起来与您正在使用的堆栈略有不同:

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

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

于 2010-12-30T22:01:02.663 回答
0

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

于 2010-12-30T20:09:38.217 回答