WinAPI 调用 Epson P50 的 DeviceCapabilities(DC_ENUMRESOLUTIONS) 总是报错

Posted

技术标签:

【中文标题】WinAPI 调用 Epson P50 的 DeviceCapabilities(DC_ENUMRESOLUTIONS) 总是报错【英文标题】:WinAPI call to DeviceCapabilities(DC_ENUMRESOLUTIONS) for Epson P50 always report error 【发布时间】:2016-01-21 07:51:02 【问题描述】:

我遇到了一些奇怪的行为 - 在 Windows 中枚举 Epson 墨水打印机的分辨率似乎是不可能的。 特别是这段代码总是报错:

int r, err;
char szBuffer[0x4000];
String prnName = "EPSON P50 Series";
String portName = "USB002";

r = DeviceCapabilities(prnName.c_str(), portName.c_str(), DC_ENUMRESOLUTIONS, NULL, NULL);
err = GetLastError();
printf("\n 1.DevCap.result = %d, err = %d", r, err);

r = DeviceCapabilities(prnName.c_str(), portName.c_str(), DC_ENUMRESOLUTIONS, szBuffer, NULL);
err = GetLastError();
printf("\n 2.DevCap.result = %d, err = %d", r, err);

在输出中我看到以下内容:

1.DevCap.result = -1, err = 0
2.DevCap.result = -1, err = 13

注意:Windows 错误 13 是 ERROR_INVALID_DATA

能否请您帮助我理解 - 如何正确解释? 这是否意味着爱普生墨水打印机的驱动程序不提供有关支持的打印分辨率的任何信息? 还是真的传递了一些无效的参数?如果有,可能是哪一个?

提前谢谢你。

PS。 请注意以下几点:

1) 打印机和端口名称正确。它们是通过EnumPrinters() WinAPI 调用获得的。在这个代码示例中,我切断了所有不相关的代码,所以只保留失败的函数。

2) 打印机本身工作正常,我可以在上面打印文档和照片。

3) 我还添加了一台“Epson Stylus 300”打印机,该打印机配置为使用“FILE:”端口进行打印。有趣的是 - 为此类打印机调用 DeviceCapabilities(DC_ENUMRESOLUTIONS) 也会报告错误# 13。这就是为什么我倾向于认为所有 Epson 墨水打印机都不提供任何有关打印分辨率的信息...

4) 所有其他对DeviceCapabilities() 函数的调用(对于DC_PAPERS, DC_PAPERSIZEDC_PAPERNAMES 等)都适用于这些打印机(Epson P50 和 Epson Stylus 300)。所以,打印机名称和端口名称是正确的,只有DeviceCapabilities(DC_ENUMRESOLUTIONS)调用存在问题。

【问题讨论】:

应该是直截了当的。这两款打印机很可能不支持DC_ENUMRESOLUTIONS 标志。安装另一家公司的打印机,它可能会工作。 是的,我知道它适用于其他打印机。该软件工作了多年,直到现在我尝试打印到爱普生时才遇到这个问题。我只是有点困惑打印机没有提供支持的分辨率列表,这对我意味着什么?我可以指定 resolution=12345 并期望看到正确的打印输出吗? 【参考方案1】:

这似乎是那些爱普生打印机的错误。但是,分辨率值取决于设备,无论如何您都不需要它。

您可能希望通过DEVMODE 获取打印机分辨率,然后将其报告给用户:

PRINTDLG pdlg =  sizeof PRINTDLG ;
pdlg.Flags = PD_RETURNDEFAULT | PD_RETURNDC;
PrintDlg(&pdlg);

DEVMODE* dm = (DEVMODE*)::GlobalLock(pdlg.hDevMode);
cout << "dm->dmDeviceName: " << dm->dmDeviceName << endl;

if (dm->dmFields & DM_PRINTQUALITY)

    cout << "dm->dmPrintQuality: " << dm->dmPrintQuality << endl;


::GlobalUnlock(pdlg.hDevMode);

dmPrintQuality 是打印机分辨率或以下与设备无关的值之一:

#define DMRES_DRAFT         (-1)
#define DMRES_LOW           (-2)
#define DMRES_MEDIUM        (-3)
#define DMRES_HIGH          (-4)

如果用户想要更改此值,最好允许访问打印机自己的设置对话框。

【讨论】:

【参考方案2】:

我确认了 EPSON Stylus Photo RX595 系列的问题。

Barmak Shenmirani 是正确的,DEVMODEdmPrintQuality 字段将指示负常数之一,以粗略了解分辨率或水平分辨率的正值(以每英寸像素为单位)。在后一种情况下,您可以从DEVMODEdmYResolution 字段中获取垂直分辨率。

如果您使用 EnumPrinters 和级别 2 (PRINTER_INFO_2) 来获取名称和端口,那么您已经拥有默认 DEVMODE 的副本。

假设任何出现故障的打印机DC_ENUMRESOLUTIONS 只有一个分辨率,这似乎是一种合理的启发式方法,它是默认DEVMODE 中的分辨率。您可以尝试调出打印对话框并调整它提供的各种质量旋钮,以查看生成的DEVMODE 中的分辨率是否不同,但我怀疑它会改变。

对于我的打印机,DEVMODE 中报告的每英寸 360×360 像素分辨率似乎是一个抽象值,因为打印机的规格声称“5760×1440 优化 dpi”。据推测,驱动程序会抖动所有这些点以实现 360×360 像素的有效密度。

为确保这不仅仅是我的编码错误,我还为我的激光打印机(兄弟)运行了它,它报告了两种分辨率:600×600 和 300×300。

【讨论】:

我需要知道重新计算条码图像的分辨率才能以正确的尺寸打印。但正如我所见——我几乎可以指定任何分辨率——比如 300 或 600——似乎它适用于我的 Epson P50。当然,在 P50 上一直打印条码不是目标,我只需要一些真正的硬件来测试我们的软件。 P50 是我附近的唯一选择... 高分辨率打印机可能会在任何合理分辨率的来源上做得很好。

以上是关于WinAPI 调用 Epson P50 的 DeviceCapabilities(DC_ENUMRESOLUTIONS) 总是报错的主要内容,如果未能解决你的问题,请参考以下文章

如何安全地调用 TerminateThread 和 FreeLibrary (WinAPI, C++)

调用 GetClientRect winAPI

华为p50和p50pro参数对比 华为p50pro和p50区别

如何使用 ollydbg 为 winApi 函数调用创建断点,例如GetDigiItemA 函数调用的断点? [关闭]

在 MFC C++ App 中实现外部 WINAPI 调用

使用目标文件调用winapi函数[关闭]