PDF 打印机仅在未设置输出文件名时生成 PDF

PDF printer generates PDF only when output file name is not set

以下代码片段将 PostScript 内容(保存在 pBuf 缓冲区中)发送到 CutePDF 打印机:

if (OpenPrinter(printerName, &hPrinter, NULL))
{
  DOC_INFO_1 di1;
  di1.pDatatype = L"RAW";
  di1.pDocName = L"Raw print document";
  di1.pOutputFile = NULL;
  StartDocPrinter(hPrinter, 1, (LPBYTE)&di1);
  StartPagePrinter(hPrinter);   
  DWORD dwWritten = 0;
  WritePrinter(hPrinter, pBuf, dwBufSize, &dwWritten);
  EndPagePrinter(hPrinter);
  EndDocPrinter(hPrinter);
}

在执行此代码期间,会出现一个对话框,我可以在其中指定输出文件的名称(例如 D:/out.pdf),然后生成 pdf 文件。到目前为止,一切都很好。当我试图通过更改代码段的第 4 行来避免文件名指定步骤时,问题就开始了:

di1.pOutputFile = L"D:/out.pdf";

此类代码在执行期间不显示对话框(如预期),但结果 D:/out.pdf 不是 pdf 文件,它是发送到打印机的 PostScript 文件的副本(副本pBuf 缓冲区的内容)。 PDF Writer 的行为方式相同。为什么 PDF 打印机会以这种方式运行,我如何才能实现所需的行为(生成 PDF 文件而不在 UI 中指定其名称)?

Windows 打印系统以这种方式运行,因为,直白地说,这就是它应该运行的方式。如果您在此时指定文件名,则打印系统会将输出发送到该文件。如果您不指定文件名,那么它将继续进行正常处理。

通常您会将打印机驱动程序输出发送到端口,对于 PDF 打印机,自定义端口监视器会获取输出(在本例中为 PostScript)并进一步处理。对于 PDF 打印机,他们将 PostScript 发送到将 PostScript 转换为 PDF 的过程(几乎总是使用 Ghostscript,尽管 Adob​​e 打印到 PDF 工具的工作方式相同)。

如果您想改变 PDF 过程的输出(即将其写入不同的文件),那么您需要改变 端口监视器 的工作方式,而不是打印子系统的工作方式,这就是您的代码当前正在做的事情。通过在您所在的位置设置文件名,您只是使进程短路,从不调用端口监视器,这就是 'save file' 对话框不出现以及输出为 PostScript 的原因。

可能有一种方法可以指定为您正在使用的特定 PDF 打印机记录的输出文件。如果没有,那么对于开源产品(如果 GS 是内置的,它们应该获得 GPL 许可),您可以索取该产品的源代码副本并根据自己的需要进行修改。

或者,您可以获取一份 Ghostscript 和 RedMon(开源端口监视器)并创建您自己的工具来完成相同的工作。