为什么 getSupportedAttributeValues 返回纸张类型

问题描述 投票:0回答:1

以下代码片段应返回打印机可用的介质托盘。

但是,对于某些驱动程序,特别是

Ricoh PCL6 Driver for Universal Print
HP Universal Printing PCL 6
,除了打印机纸盒外,这些驱动程序还列出纸张类型,例如
Recycled
Thick
Matte
等。

据我所知,OpenJDK 在调用

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

    

java winapi printing printer-control-language
1个回答
1
投票

短:

匹配
    Ricoh|HP
  • PCL6|PCL 6
     上的驱动程序名称
    
    过滤所有托盘 ID > 1000
  • 长:

某些驱动程序(例如 HP)会在其他区域正确暴露打印机托盘,例如:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Print\Printers\<PRINTER_NAME>\PrinterDriverData
    • InputSlot
    • InputSlotDisplayNames
    • 
      
  • ...但是对于像理光这样的驱动程序来说,情况并非如此。

在检查了很多驱动程序(HP、Ricoh、Xerox、Konica 等)后,我将问题分为以下几个方面:

PCL6 驱动程序
  • HP 或 Ricoh 作为供应商
  • 在两个供应商的情况下,
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。
从 Java 中查找托盘 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>
    • 
      
    计算驱动程序名称是一些微妙的代码,但可以可靠地使用。 有关完整的代码示例,请参阅
  • here
。 特别注意键/值中的特殊字符替换。

找到驱动程序后,使用正则表达式匹配术语 Ricoh

HP

PCL6
PCL 6
 将允许过滤超过 1,000 个托盘 ID。
通过结合上述托盘Id编号、供应商匹配以及关键字“PCL6”和“PCL 6”的技术,可以通过编程方式过滤掉坏托盘。

© www.soinside.com 2019 - 2024. All rights reserved.