如何在Windows中控制打印机托盘选择?

5
我们需要能够更改给定打印机的默认选定打印纸盒。有没有VC++/win32代码可以做到这一点?
如果有关系的话,我认为我们必须更改打印机的默认设置。我们的打印作业是由其他应用程序执行的,因此我们无法在从我们的应用程序内部发起的打印操作的上下文中进行这些更改。除非有某种方法可以在不同的应用程序中修改默认打印设置,否则我认为我们将改变用户对打印机的默认设置,启动我们的打印作业,然后将默认设置恢复为原始值。
我们真的希望仅更改当前用户的默认设置,而不需要任何特殊的UAC提升等...
我怀疑它将使用类似于此MSDN文章中所示的内容,并涉及在DEVMODE结构中设置字段(dmDefaultSource或dmFormName或两者兼有)。
有人愿意试试吗?还是有人有任何要分享的注意事项?
编辑:这里是DEVMODE文档DEVMODE documentation 编辑:我还应该指出,我们正在寻找通用解决方案-而不是针对特定打印机的解决方案(我们在许多环境中部署)。
5个回答

2
FYI - 我们最终采用的解决方案是捕获 DEVMODE 结构。我们有一个小型的 Win32 应用程序,通过 DocumentProperties(fMode 设置为 DM_IN_PROMPT)显示打印机设置对话框。然后将生成的 DEVMODE 保存到磁盘上。在进行打印时,我们捕获当前的 DEVMODE,设置存储的 DEVMODE,启动打印,然后恢复原始 DEVMODE。
这实际上非常有效。偶尔,打印驱动程序会更新并导致存储的 DEVMODE 失效,但这种情况并不经常发生,用户很容易修复它。
作为额外的奖励,这种方法允许我们捕获所有的打印机设置(不仅仅是输出托盘),因此我们能够支持高级设置,如装订、整理等。
提示:如果您尝试这个方法,请确保将其写入磁盘作为二进制输出流。在我最初评估这种方法时,我不小心将输出流设置为文本输出流。对于许多情况,事情都可以正常运行,但对于一些使用DEVMODE私有数据中的高阶字节的打印机,会突然出现问题。这是一个愚蠢但容易犯的错误,而且一度使一个非常好的解决方案无法实现。

你是否有兴趣进一步扩展你的答案呢?如何捕获当前DEVMODE?如何用存储的替换它呢? - B H
当然可以 - 您可以使用不同的fMode值来调用DocumentProperties函数。 - Kevin Day
1
这个链接有更多的描述和一些C#代码示例。http://nicholas.piasecki.name/blog/2008/11/programmatically-selecting-complex-printer-options-in-c-shar/ - Andrew Cash

1

dmDefaultSource 控制托盘。不幸的是,您想要设置的值取决于您的驱动程序,因为这是一个二进制编号,不一定与打印机上印有的托盘号相同。

以下链接提供了一些 VB6 代码,用于收集有关打印机托盘/箱分配的信息。您可以使用该信息将 dmDefaultSource 编程分配给托盘的适当箱号。您基本上需要使用 DeviceCapabilities 返回有关打印机的信息,然后搜索字符串(例如“托盘1”)以获取相关联的箱号。

http://support.microsoft.com/kb/194789


这看起来非常有前途 - 我会在有时间的时候回复并试一试 - 谢谢! - Kevin Day

1

设置这样的功能可能会很棘手,特别是如果驱动程序不遵循微软的打印准则。话虽如此,我们使用System.Drawing.Printing.PrinterSettings取得了一些成功。您可以设置PaperSource,但我不确定是否可以设置默认值。

如果您还没有看到这个例子,您可能需要进一步研究一下它。它描述了一种存储和重新加载打印机设置的方法。我的一个伙伴向我指出了这一点: PrinterSettings - Changing, Storing and Loading Printer Settings

另一种方法可能适用于您,也可能不适用于您,就是确定您所需的少数设置。安装具有每个设置(即托盘1、托盘2)的打印机。然后只需在打印时切换默认打印机。这不是您要寻找的,但它可能有所帮助。

在这些情况下,我们通常会让第三方应用程序将数据写入我们正在监视的文件夹,然后我们拾取文件并自己解析后缀或PCL,并更改纸盘,然后发送到目标设备。听起来比较简单。


这是与当前应用程序相关的设置的良好参考。如果我的应用程序启动打印作业,它将完美地工作。但是我们正在指示另一个应用程序启动打印作业,因此我们需要更改其他应用程序中的设置或更改默认的系统范围设置。 - Kevin Day

0

最近我在一个特定打印机驱动程序上做了非常类似的事情,需要使用供应商特定的SDK。托盘似乎没有出现在DEVMODE或任何其他PRINTINFO_*结构中,所以我想我会给打印机供应商发一封电子邮件。

作为最后的手段,我能想到两种可能的黑客方法。一种是使用脚本工具(如AutoIT)在GUI级别自动化驱动程序。第二种是将注册表转储到文件中,更改驱动程序设置,再次转储注册表,并比较差异(可能有效,也可能无效)。


DEVMODE有两个参数(dmDefaultSource和dmFormName),似乎控制托盘。我是否误解了这些成员的控制作用? - Kevin Day

0

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