在Windows中打印时,通过编程设置每张纸上的页面数(N-Up)选项

4
我需要一种编程方式来设置打印时每页的纸张数。我知道用户可以通过打印机设置对话框选择此选项,如果需要的话,我也可以显示这样的对话框。但是在我正在开发的程序上下文中,我需要软件自己选择,而不需要用户深入了解打印机设置。虽然似乎可以使用 DEVMODE 结构的 dmNup 成员询问 Windows 打印机是否支持此功能,但似乎没有任何官方方法实际设置当前打印作业的该选项。显然,一种解决方案是修改我的软件中的打印算法,以便在设备上下文中适当地布置页面,从而在生成的输出中获得多个页面每张纸。然而,我还没有看到任何简单的方法来做到这一点,这不需要在所有绘制到打印机设备上下文的代码中进行重大更改。由于各种原因,我宁愿避免大量代码更改。
另一种解决方案是在Windows中安装多个打印机副本,同时将它们全部指向同一个打印机端口。每个打印机副本都设置了不同的默认每页纸张数。然后软件可以选择适当的打印机,最终结果就像程序选择了必要的每页纸张选项一样。但是,我在这种方案中遇到了各种问题,因此我正在寻找一种更少负担的替代方案。 本文提供了另一个可能的解决方案:操作紧随官方DEVMODE结构之后的私有驱动程序数据中的适当字节。问题在于,并没有保证任何特定的打印机驱动程序实际上使用相同的字节,而我需要支持基本上可以在办公环境中使用的任何打印机。似乎我的软件需要一个配置,以便我可以为不使用默认值的驱动程序指定不同的字节偏移量。这可能是一个罕见的情况,也可能是一个频繁的头痛,具体取决于多少打印机驱动程序已经决定为此设置使用不同的字节。
所以,这里是我的问题:
  • 有人在操作私有驱动程序数据的最后一种技术方面有真实世界的经验吗?当处理来自不同制造商的各种打印机时,它的表现如何?
  • 还有其他我忽略的技术吗?
  • 如果没有其他方法,那么有没有简单的方法可以将绘制文本、线条、图形等代码传递给打印机设备上下文,并强制缩放、移动和可能旋转(对于每张纸双面打印)输出到设备上下文中的必要位置,而不编写所有代码(并且不失去1像素宽的线条)?

注:值得一提的是,我正在使用C++和MFC编写程序。但是,所有这些都同样适用于处理设备上下文和Windows API的任何程序。

3个回答

0

随着XPS在Win XP及以上版本中的实现,如果您的源应用程序是WPF/.NET应用程序,则可以使用PrintTicket作为设置NUp的机制。

http://msdn.microsoft.com/en-us/library/system.printing.printticket.pagespersheet.aspx 指定了N-Up的属性。

理想情况下,如果绘图应用程序设置了这个并调用打印驱动程序,Windows 应该设置正确的NUp设置并将其传递给底层驱动程序(GDI或XPS)。但也许这只适用于那些已实现打印票转换的驱动程序。


0

嗯,我已经有一段时间没有使用GDI和MFC了,但是过去我做了很多与打印机相关的工作。我倾向于说,由于GDI应该将您的程序从了解绘图上下文的知识中抽象出来,因此您无法针对特定的API调用进行操作。然而,可能有一些方法可以做到这一点,而不像在结构的私有区域中猛击位那样具有黑客精神。

我要做的第一件事是查看CDC::Escape方法(或Escape Win32 API函数)。在最好的情况下,有一个标准的转义序列可将打印机设置为n-up模式。在最坏的情况下,您必须找到打印机的转义序列并发送原始数据。(曾经,这是使打印机使用其花哨功能的唯一方法。)大多数打印机开始实施语言标准(PCL?HPGL?我忘记了哪一个)。如果它们仍然实现标准语言,则许多打印机可能会理解转义序列。

如果失败了,您可能需要手动在上下文中实现自己的n-up绘图,但使用SetMapMode之类的东西将单位设置为Twips(或任何有效的单位),并预先缩放绘制。

否则,尝试查看GDI在缩放方面的操作,看看是否有效。

0

我看到了一个关于如何在一张纸上打印多个页面的教程。

基本上,您需要使用文档的PageSize来缩放您的绘图,并确定每张纸上要显示的页面数量。

如果您想要每张纸上显示2页,则只需绘制文档的一半,并递增索引,以便您下一次循环迭代时在第二半部分打印。

我在我的SO问题中有代码供您查看:PrintPage PrintPageEventHandler Is Printing Too Many Copies。结果发现我错误地设置了文档中的副本数量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接