我需要告诉打印机驱动程序发出一个换页。
我直接打印到打印机使用:
OpenPrinter
StartDocPrinter
StartPagePrinter
WritePrinter
EndPagePrinter
EndDocPrinter
ClosePrinter
一组API调用。
很多灵感来自KB138594 – HOWTO:使用Win32 API将原始数据发送到打印机 。 这篇KB文章中重要的一点是他们(和我的复制代码)以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打印机:没有任何反应(即没有保存对话框,没有任何打印)。
我前一段时间询问了这个问题的一个解决scheme ,并且回应是您必须将文档模式从RAW
更改为:
docInfo.pDatatype = "RAW";
到TEXT
:
docInfo.pDataType = "TEXT";
那么这可能是因为你直接发送“RAW”数据到打印机,RAW可以是任何PDL。 但是,XPS驱动程序可能只会理解XPS,并且可能会忽略您的“unknown:Hello,world!0xFF”PDL。 如果有的话,XPS驱动程序可能只会在您直接写入时接受XPS数据。
如果要在XPS驱动程序上呈现文本,则应使用GDI。 如果将“TEXT”指定为数据types,则可以将纯文本发送到驱动程序。 附在驱动程序上的打印处理器将通过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>打印机:换页不会发生 – 大概是因为我不再打印在“原始打印机命令”模式。
所以我需要的是Windows-ish发布换页的方式。 我需要的API调用将告诉打印机驱动程序,我希望打印机执行换页。
我的问题:如何告诉打印机在打印期间发送一个Form-Feed?
打印处理器通知后台打印程序根据文档数据types更改作业。 它与打印机驱动程序配合使用,将假脱机的打印作业从硬盘驱动器发送到打印机。
软件供应商偶尔会开发自己的打印处理器来支持自定义数据types。 通常,打印处理器不需要pipe理员进行任何设置或干预。
数据types
Windows打印过程通常支持五种数据types。 在客户端计算机和打印服务器计算机上,两种最常用的数据types(增强型图元文件(EMF)和准备打印(RAW))以不同方式影响性能。
RAW
是除基于Windows的程序以外的客户端的默认数据types。 RAW数据types告诉假脱机程序在打印之前不要改变打印作业。 使用这种数据types,准备打印作业的整个过程是在客户端计算机上完成的。
EMF
或增强型图元文件是大多数基于Windows的程序的默认数据types。 使用EMF,打印的文档被转换成比RAW文件更便携的元文件格式,通常可以打印在任何打印机上。 EMF文件通常比包含相同打印作业的RAW文件要小。 就性能而言,只有打印作业的第一部分被更改或呈现在客户端计算机上,但大部分影响都在打印服务器计算机上,这也有助于客户端计算机上的应用程序更快地将控制权交还给用户。
下表( 摘自MSDN )显示了默认的Windows打印处理器所支持的五种不同的数据types:
数据types : RAW
后台处理程序的指示 :无需更改即可打印文档。
使用 :这是所有不基于Windows的客户端的数据types。
数据types : RAW [FF appended]
后台打印程序的指示 :附加一个换页符(0x0C),但不作其他更改。 (如果没有结尾的换页,PCL打印机将省略文档的最后一页。)
使用 :一些应用程序需要。 Windows不分配它,但可以在“打印处理器”对话框中将其设置为默认值。
数据types : RAW [FF auto]
后台打印程序的方向 :检查一个尾随的换页,如果还没有,则添加一个,但不作其他更改。
使用 :一些应用程序需要。 Windows不分配它,但可以在“打印处理器”对话框中将其设置为默认值。
数据types : NT EMF 1.00x
后台打印程序的指示 :将文档视为增强型图元文件(EMF),而不是打印机驱动程序放出的RAW数据。
用途 :EMF文件由Windows创build。
数据types : TEXT
后台处理程序的指示 :将整个作业视为ANSI文本,并使用打印设备的出厂默认设置添加打印规格。 使用 :当打印作业是简单文本并且目标打印设备不能解释简单文本时,这非常有用。
您可以通过控制面板中打印机的属性查看打印机可用的打印处理器以及每个处理器支持的数据types:
是的,这是行不通的。 您有意绕过打印机驱动程序,即为任何打印机提供通用接口的代码块。 这使您可以处理每种特定打印机型号的特性。
有一些常见的接口,你在你的代码中使用的是旧的点阵打印机使用的接口。 PCL在Hewlett Packard激光打印机上很常见。 后记在高端打印机上很常见。 后两者有他们自己的咒语来换取饲料。
然后是便宜的激光和喷墨打印机的海洋。 他们通常根本没有明确的界面。 打印机内部没有将打印机命令转换成纸上点的处理器,而是让打印机驱动程序尽一切努力。 你永远不会得到其中的一个,界面是专有的,没有记录。
打印机驱动程序是你的朋友在这里。 PrintDocument类使用它。 获取表单提要很简单,只需设置e.HasMorePages = true并退出PrintPage事件处理程序。 您已经看到了我链接的StreamPrinter类。
我不熟悉TEXT
文档类型,但我认为这只是最低的公分母“哑打印机”表示。 如果是这样,它可能会识别一个换页字符,除了你已经使用了错误的字符 – 它不是0x12
或0xFF
,它是0x0c
。 见http://en.wikipedia.org/wiki/Ascii
由于我的最后一个答案没有帮助,让我们试试看。 你有没有试图做EndPagePrinter
其次是StartPagePrinter
当你需要一个分页StartPagePrinter
?
如果这仍然不起作用,你可能需要用GDI来做到这一点。 这个堆栈看起来与你正在使用的堆栈略有不同:
CreateDC
CreateFont
SelectObject
StartDoc
StartPage
TextOut
EndPage
EndDoc
DeleteDC
您将被要求管理一种字体,并将文本放置在每一行的位置上。