【问题标题】:Delphi XE8 Printe VCL and DocumentProperties strange issueDelphi XE8 Printe VCL 和 DocumentProperties 奇怪的问题
【发布时间】:2015-12-02 04:46:35
【问题描述】:

我正在使用 vcl.printers 单元 (delphi XE8),在与打印机“对话”时遇到错误。

我追踪到 vcl.printers 并找到了这段代码(由 EMB 人编写):

if OpenPrinter(ADevice, FPrinterHandle, nil) then
 begin
  if DeviceMode = 0 then  // alloc new device mode block if one was not passed in
begin
  DeviceMode := GlobalAlloc(GHND,
    DocumentProperties(0, FPrinterHandle, ADevice, nil, nil, 0));

  if DeviceMode <> 0 then
  begin
    DevMode := GlobalLock(DeviceMode);
    if DocumentProperties(0, FPrinterHandle, ADevice, DevMode^,
      DevMode^, DM_OUT_BUFFER) < 0 then
    begin
      GlobalUnlock(DeviceMode);
      GlobalFree(DeviceMode);
      DeviceMode := 0;
      DevMode := nil;
    end
  end;
end;
if DeviceMode <> 0 then
  SetPrinterCapabilities(DevMode^.dmFields);
end;

DocumentProperties(0, FPrinterHandle, ADevice, nil, nil, 0)

第一次返回正确的缓冲区大小(我没有在某处写它),然后通过第二次执行时间它返回 4294967295 字节,确实是 -1,因为声明错误,但意味着错误。 如您所见,由于没有错误检查,VCL 代码对错误的处理非常差! 但是我这里有什么错误,为什么?

DocumentProperties 位于 winspool.dll 中

要从中恢复,我需要重新启动 PC,但我不能使用超过一次,这对于调试来说非常烦人。 打印机只是“PDFcreator”

我在其他电脑上试过,即使我运行了很多次也似乎没问题。

我还有两台激光网络打印机。

谢谢

【问题讨论】:

  • 在您发布的对DocumentProperties 的两次调用中都有错误检查。首先是对DeviceMode &lt;&gt; 0的测试,通过了;第二个是DocumentProperties() &lt;&gt; 0 的测试。第一次调用请求分配适当大小的内存,第二次调用该内存块以供函数填充。贴出的代码没有错误;您对其用途的理解是错误的。
  • 看来 DocumentProperties(0, FPrinterHandle, ADevice, DevMode^, DevMode^, DM_OUT_BUFFER) 不正确,这个更好我认为 DocumentProperties(0, FPrinterHandle, ADevice, DevMode^, NIL, DM_OUT_BUFFER)这段代码是Embarcadero的一个库,我没写过。
  • 不,代码(如发布的)是正确的。它已经运行了十多年,现在可以在 Windows 10 和 XE 10 Seattle 中运行。根据 MSDN 的文档,这也是正确的。
  • 那么为什么我会从这个函数中得到 -1 呢?我找到了这个qc.embarcadero.com/wc/qcmain.aspx?d=107919
  • 我不知道你为什么会得到任何东西,因为你还没有发布任何自己的代码。我所能说的只是您发布的代码,它是基于 MSDN 文档的正确性,并且我使用了自 Delphi 1 以来所有操作系统版本和 Delphi 版本中包含的打印机代码,没有问题。在您与打印机“交谈”(无论这意味着什么)的您自己的代码中可能出了什么问题,我无法判断,因为我看不到您的代码。 (您链接的 QC 报告指出了已修复的任何问题。如果确实有修复,它将在西雅图。)

标签: windows api delphi printing delphi-xe8


【解决方案1】:

过去,我确实遇到过与两个客户相同的问题。我确实将其追踪到打印机单元 (printers.pas),如果没有在我国其他地方的远程计算机上使用调试器,很难追踪它。

好的..但我确实一直跟踪到这一行:

DeviceMode := GlobalAlloc(GHND, DocumentProperties (0, FPrinterHandle, ADevice, StubDevMode, StubDevMode, 0));在 PRINTERS.PAS 单元中的函数 SetPrinter 中

当我确实将它分成两行时,即首先调用 DocumentProperties 并将值存储在整数变量中,然后检查该值,然后才在值大于 0 时调用 Globalalloc 并使用存储的值对其进行调试如果我没记错的话,在调试文件中,错误确实出现在 SPOOL.DLL 的 DocumentProperties 函数中。此函数返回 -1 作为设备的大小,但仅限此客户在一台计算机上(他在我的程序中使用 4 或 5)

在我的所有客户(接近 200 个客户)中,我在两台计算机上都遇到过这个问题。另一个自己修复了它。我不知道它是如何修复的。几分钟前我试图修复后一个。最后我找到了解决方案。我确实通过快捷方式的简单更改修复了这个客户。我开始在 Windows 10 中使用自动修复来实现兼容性,然后运行“测试程序”按钮,它工作了。选择打印机或使用它的属性没有错误。好的..然后我再次尝试单独使用快捷方式.. aarrgg.. 错误返回.. 但是,啊哈.. 我心想“这必须连接到 Windows 运行该程序的方式”并更改了 Windows 10 的运行方式程序为选中“以管理员身份运行”以取消选中。

没问题。

在几乎所有使用 Windows 10 的计算机上,我都会毫无问题地选中“以管理员身份运行”。我认为连接这些点的 spool.dll 存在更新或一些问题。

ps。 如果你用谷歌搜索这种行为与 Delphi DocumentProperties 问题,那么你会发现这是已知问题。有人说连接到 x86 和 x64 模式,但我发现了这一点。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-19
    • 2019-09-20
    • 2012-04-18
    • 2011-01-31
    • 2023-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多