呈现打印作业

重要

建议使用 Microsoft 的 IPP 收件箱类驱动程序,以及 Print Support Apps (PSA) ,在 Windows 10 和 11 中自定义打印体验,以便进行打印机设备开发。

有关详细信息,请参阅 打印支持应用设计指南

打印作业要么在创建时呈现,要么作为 EMF 记录写入后台打印文件。 对于 EMF 记录,当 EMF 打印处理器 (localspl.dll) 播放记录时,将进行呈现。 呈现包括对用户模式 GDI 绘图函数的一系列调用,从 CreateDC 开始。 对 CreateDC 的调用是一系列应用程序调用中的第一个调用,这些调用导致涉及图形呈现引擎 (GRE(也称为内核模式 GDI) )和打印机图形 DLL 的操作链。

下图显示了调用 CreateDC 后内核模式 GDI 与打印机图形 DLL 之间的交互。

说明调用 createdc 后内核模式 gdi 与打印机图形 dll 之间的交互的示意图。

  1. 当应用程序调用 CreateDC 函数来创建打印机设备上下文时,GDI 会检查是否已加载相应的打印机图形 DLL。 如果不是,GDI 将加载 DLL 并在 DLL 中调用 DrvEnableDriver 函数。 除非重新加载驱动程序,否则不会再次调用 该函数。

  2. 接下来,GDI 调用打印机图形 DLL 的 DrvEnablePDEV 函数,以便驱动程序可以创建物理设备实例并返回设备特征。 GDI 使用返回的信息创建设备实例的内部说明。

  3. 然后,GDI 调用图形 DLL 的 DrvCompletePDEV 函数,为设备实例提供 GDI 句柄。 图形 DLL 必须使用此句柄作为 GDI 绘图引擎提供的一些 以 Eng 为前缀的回调的输入 (请参阅 GDI 支持服务) 。

  4. GDI 收到设备实例句柄后,调用图形 DLL 的 DrvEnableSurface 函数,该函数设置图面进行绘制,并将其与物理设备实例相关联。

  5. 驱动程序可以通过调用 EngCreateBitmap 为设备实例创建绘图图面。 或者,如果绘图图面由设备管理,驱动程序可以调用 EngCreateDeviceSurface

  6. 如果 EngCreateBitmap 无法提供足够大的位图来包含整个物理页,并且驱动程序支持页面镶边,则可以调用 EngMarkBandingSurface 来通知 GDI 将采用镶边。

  7. 最后,必须调用 EngAssociateSurface 以允许 GDI 将创建的图面与指定的设备实例相关联,并让 GDI 知道驱动程序提供的图形 DDI 绘图函数 ((如果有任何) 它在此特定图面上绘制时应调用)。

此时,已创建绘图图面,可以开始渲染。 GDI 调用的函数取决于条带是否有效。

使用中的镶边

对于在使用镶边时要呈现的每个文档,GDI 在打印机图形 DLL 中调用以下函数:

DrvStartDoc

对于每个物理页面

DrvStartPage

DrvStartBanding

对于物理页上的每个带状传递

DrvQueryPerBandInfo

呈现操作

DrvNextBand // 发送此波段的光栅数据,然后清除图面以与下一个波段重复使用

DrvEndDoc

未使用镶边

对于不使用镶边时要呈现的每个文档,GDI 在打印机图形 DLL 中调用以下函数:

DrvStartDoc

对于每个物理页面

DrvStartPage

呈现操作

DrvSendPage // 发送页面的光栅数据

DrvEndDoc

DrvQueryPerBandInfo 外,这些函数旨在允许打印机图形 DLL 通过调用 EngWritePrinter) 将控制序列发送到打印机硬件 (,并执行初始化或完成文档、页面或带区处理所需的任何内部操作。

打印机图形 DLL 负责将呈现的图像发送到 (,即通过调用 EngWritePrinter) 在适当时间) 绘图图面的内容 (发送到打印机,如下所示:

  • 对于 GDI 托管或设备管理的位图面

    绘图图面是 GDI 提供的或驱动程序提供的位图。 打印机图形 DLL 可能会挂钩某些绘图函数, (surface 协商) 。 如果使用页面镶边, DrvNextBand 函数应发送绘图图面内容。 如果未使用镶边, DrvSendPage 函数应发送绘图图面内容。

  • 对于设备管理的矢量图面

    绘图图面位于设备内。 打印机图形 DLL 挂钩所有绘图函数 (surface 协商) ,这些函数在呈现操作期间将图像数据发送到打印机。 不使用页面镶边。

如果预计打印机图形 DLL 提供的任何图形 DDI 函数的执行时间可能超过 5 秒,则应包含至少每 5 秒调用 EngCheckAbort 的代码,以查看打印作业是否应终止。

在 GDI 调用 DrvEndDoc 以指示文档已完全呈现后,它将调用 DrvDisableSurface。 如果 DrvEnableSurface 名为 EngCreateBitmap,则 DrvDisableSurface 必须调用 EngDeleteSurface

当应用程序调用 DeleteDC 时,GDI 会调用打印机图形 DLL 的 DrvDisablePDEV 函数。

如果应用程序在打印文档期间调用 ResetDC 函数,GDI 将创建新的设备上下文,并为新上下文调用打印机图形 DLL 的 DrvEnablePDEV 函数。 然后 GDI 调用 DrvResetPDEV 函数,因此图形 DLL 可以使用旧上下文中的信息更新新上下文。 接下来,对旧上下文调用 DrvDisableSurfaceDrvDisablePDEV ,然后为新上下文调用 DrvEnableSurface 。 最后,GDI 调用 DrvStartDoc 并在新页面上恢复呈现。

GDI 在卸载打印机图形 DLL 之前调用 DrvDisableDriver

如果打印机硬件支持 GDI 绘图函数不支持的绘图操作,则打印机图形 DLL 可以提供 DrvDrawEscape 函数。

如果需要支持无法通过 GDI 函数使用的绘图或非绘制操作,打印机图形 DLL 可以提供 DrvEscape 函数。 例如, Microsoft PostScript 打印机驱动程序 使用转义来支持 PostScript 注入点。 或者,应用程序可能需要获取传真机的电话号码。 DrvEscape 函数还用于指示 DrvDrawEscape 函数支持的操作。