以下代码片段应返回打印机可用的介质托盘。
但是,对于某些驱动程序,特别是
Ricoh PCL6 Driver for Universal Print
和 HP Universal Printing PCL 6
,除了打印机纸盒外,这些驱动程序还列出纸张类型,例如 Recycled
、Thick
、Matte
等。
DC_BINNAMES
时正确使用 DeviceCapabilities
。 OpenJDK 在源代码中似乎根本没有使用DC_MEDIATYPENAMES
,所以我不期望例如
Purple Paper
甚至是一个可查询的属性,但它在从理光驱动程序查询托盘时列出。那怎么了? 这些 PCL 6 驱动程序是否被窃听了? DeviceCapabilities
有错吗?或者这个 bug 存在于 OpenJDK 中吗?
import javax.print.DocFlavor;
import javax.print.PrintService;
import javax.print.PrintServiceLookup;
import javax.print.attribute.standard.Media;
public class TrayListing {
public static void main(String ... args) {
String printerName = "HP LaserJet ..."; // TODO: change this to the actual printer name
PrintService[] allPrinters = PrintServiceLookup.lookupPrintServices(null, null);
for(PrintService ps : allPrinters) {
if(ps.getName().equalsIgnoreCase(printerName)) {
// loop over media trays
System.out.println("\n\nFound MediaTray:");
// Some HP, Ricoh printers/drivers list items that aren't printer trays, such as paper types
for(Media m : (Media[])ps.getSupportedAttributeValues(Media.class, DocFlavor.SERVICE_FORMATTED.PAGEABLE, null)) {
if (m instanceof javax.print.attribute.standard.MediaTray) {
System.out.println("- " + m + " (" + m.getClass().getName() + ")");
}
}
}
}
}
}
其他关键字:
PCL XL Feature Reference
短:
Ricoh|HP
PCL6|PCL 6
上的驱动程序名称过滤所有托盘 ID > 1000
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\<PRINTER_NAME>\PrinterDriverData
InputSlot
InputSlotDisplayNames
在检查了很多驱动程序(HP、Ricoh、Xerox、Konica 等)后,我将问题分为以下几个方面:
PCL6 驱动程序
DC_BINS
值始终> 1000,这在
PCL6
MediaSource
规范中进行了部分解释,引用:
”...外部输入托盘 1
至值(不是
248
是 通过将值8
替换为255
表示枚举值。例如,8
=first external input tray
,9
=second external input tray
,等等...”虽然没有具体说明 1,000,但 Xerox 等供应商使用的值超过 7000 而没有错误。 也就是说,对于有问题的供应商,我们观察到,当值 > 1,000 时,它们往往是实际有效的MediaType
MediaSource
值),但会增加 1,000。
奇怪的是,这仅限于 HP 和 Ricoh,不适用于其他 PCL 驱动程序。 例如:
柯尼卡使用的托盘ID为
1000
LCT
,即“大容量托盘”,这是有效的。
Xerox 提供 PCL6 驱动程序,但通常使用高于 1000 的托盘 ID,例如
7153
Tray 1
,
7154
=
Tray 2
。
Ricoh 已知在其 PCL5 版本的驱动程序中使用托盘 ID
1025
1025
=
Auto Tray Select
,但对于他们的 PCL6 驱动程序似乎并非如此,混合了
MediaType
值。为了“解决”这个问题,我编写了一系列自定义解析来找出驱动程序供应商和托盘 ID。
// Get default printer
PrintService ps = PrintServiceLookup.lookupDefaultPrintService();
for(Media mediaTray : (Media[])ps.getSupportedAttributeValues(Media.class, null, null)) {
// Warning: Reflective operation on Windows-only class
Method method = ps.getClass().getMethod("findTrayID", MediaTray.class);
Object trayId = method.invoke(ps, new Object[]{mediaTray});
System.out.println(trayId);
}
从 Java 获取驱动程序供应商:
这部分比较复杂,需要第三方依赖,JNA。 因此,我省略了代码,但我将提供步骤:
Advapi32Util.registryGetStringValue(...)
了解哪个注册表字符串值来获取驱动程序名称是一项复杂的操作,但以下方面很有帮助:
HKLM\SYSTEM\CurrentControlSet\Control\Print\Printers\<PRINTER_NAME>\Printer Driver
HKLM\Software\Microsoft\Windows NT\CurrentVersion\Print\Providers\Client Side Rendering Print Provider\Servers\<PRINTER_NAME>\Printers\<GUID>
找到驱动程序后,使用正则表达式匹配术语 Ricoh
HP
、
PCL6
和
PCL 6
将允许过滤超过 1,000 个托盘 ID。
通过结合上述托盘Id编号、供应商匹配以及关键字“PCL6”和“PCL 6”的技术,可以通过编程方式过滤掉坏托盘。