XPS 驱动程序文档事件

重要

新式打印平台是 Windows 与打印机通信的首选方式。 建议使用 Microsoft 的 IPP 收件箱类驱动程序以及打印支持应用 (PSA) 来自定义 Windows 10 和 11 中的打印体验,以便进行打印机设备开发。

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

与 GDI 打印支持向 GDI 打印驱动发送通知的方式类似,Microsoft Windows Presentation Foundation (WPF) 打印支持也会在文档后台处理过程中向 XPSDrv 打印驱动发送通知事件。 WPF 打印支持也使用与 GDI 打印支持相同的 DrvDocumentEvent DDI 函数,但定义了新的事件以支持 XPS 文档处理事件。 GDI 打印支持将继续向基于 GDI 的打印驱动程序和用于 Microsoft Win32 应用程序打印的 XPSDrv 打印驱动程序发出 DrvDocumentEvent 事件处理程序。

DrvDocumentEvent 事件处理程序概述

如有必要,XPSDrv 打印驱动程序可以从配置模块导出 DrvDocumentEvent 事件处理程序,以拦截文档处理函数。 新的 XPS 文档相关事件由一个以“DOCUMENTEVENT_XPS_”开头的符号名来标识。

WPF 打印支持调用 XPSDrv 打印驱动程序的 DrvDocumentEvent 函数,同时在后台处理要打印的文档。 每次调用都发生在流程的不同步骤。 每次调用的处理步骤由 iEsc 参数值来确定。 pvInpvOut 参数引用的缓冲区内容根据处理步骤的不同而不同。

本主题中的以下小节仅介绍 WPF 打印支持产生的 XPS 文档处理事件。

DrvDocumentEvent 事件处理程序说明

DrvDocumentEvent 事件处理程序的调用格式如下。 本部分中的代码和参数定义仅供参考。

INT
  DrvDocumentEvent(
    HANDLE  hPrinter,
    HDC  hdc,
    int  iEsc,
    ULONG  cbIn,
    PVOID  pvIn,
    ULONG  cbOut,
    PVOID  pvOut
    );

参数

hPrinter
WPF 打印支持提供的打印机句柄。

hdc
调用方提供的设备上下文句柄,由 CreateDC 调用生成。 如果 iEsc 被设置为 DOCUMENTEVENT_CREATEDCPRE,则此参数为零。

在打印文档时,系统将对 XPS 和 GDI 文档使用相同的事件值。 驱动程序必须意识到这种相似性,并根据 hdc 来确定作业类型。 hdc 等于所有 DOCUMENTEVENT_XPS_Xxx 事件的 INVALID_HANDLE_VALUE。 此检查将根据调用应用程序来确定 DrvDocumentEvent 事件值的正确解释。 此检查仅适用于 XPSDrv 打印驱动程序。

iEsc
由调用方提供的转义码,用于标识要处理的事件。 此参数可为下列整数常量之一。

DOCUMENTEVENT_QUERYFILTER
WPF 打印支持发送此事件,以查询打印驱动程序将响应的 XPS 文档处理事件列表。 此事件先于其他与 XPS 文档相关的事件发出。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRE
WPF 打印支持会在将 FixedDocumentSequence 添加到 XPS 后台处理程序文件之前发送此事件。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPOST
WPF 打印支持会在将 FixedDocumentSequence 添加到 XPS 后台处理程序文件之后发送此事件。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRE
WPF 打印支持会在将 FixedDocument 添加到 XPS 后台处理程序文件之前发送此事件。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPOST
WPF 打印支持会在将 FixedDocument 添加到 XPS 后台处理程序文件之后发送此事件。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPRE
WPF 即将在 FixedDocumentSequence(作业级别)中添加 PrintTicket。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPOST
WPF 应释放驱动程序在相应的 DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPRE 事件中返回的数据。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRINTTICKETPRE
WPF 即将在 FixedDocument(文档级别)中添加 PrintTicket。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRINTTICKETPOST
WPF 应释放驱动程序在相应的 DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRINTTICKETPRE 事件中返回的数据。

DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRINTTICKETPRE
WPF 即将在 FixedPage(页面级别)中添加 PrintTicket。

DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRINTTICKETPOST
WPF 应释放驱动程序在相应的 DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRINTTICKETPRE 事件中返回的数据。

DOCUMENTEVENT_XPS_CANCELJOB
WPF 打印支持会在调用取消作业操作前发送此事件。

DOCUMENTEVENT_XPS_COMMITJOB
WPF 已将日期写入当前文件。

cbIn
pvln 参数引用的缓冲区的大小(以字节为单位)。 此值由 WPF 打印支持提供,并由事件处理程序读取。

pvIn
由调用方提供的指针。 如下表所示,此参数的使用取决于 iEsc 值。 (对于未显示在此列表中的 DOCUMENTEVENT_XPS_Xxx 事件,不会使用 pvIn。)

DOCUMENTEVENT_QUERYFILTER
pvIn 指向 PDOCEVENT_FILTER 结构(与 DOCUMENTEVENT_QUERYFILTER 结构相同)。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRE
pvIn 指向包含三个属性的 PrintPropertiesCollection 结构(请参阅 Winspool.h):

  • EscapeCode,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG) 值。 EscapeCode 是事件值。

  • JobIdentifier,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG) 值。 JobIdentifier 是调用 GetJob() 和 SetJob() 时所需的 ID。

  • JobName,它是 EPrintPropertyType:: kPropertyTypeString (UNICODE) 值。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPOST
与 DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRE 相同。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRE
pvIn 指向包含两个属性的 PrintPropertiesCollection 结构(请参阅 Winspool.h):

  • EscapeCode,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG) 值。 EscapeCode 是事件值。

  • DocumentNumber,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG) 值。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPOST
与 DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRE 相同。

DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRE
pvIn 指向包含两个属性的 PrintPropertiesCollection 结构(请参阅 Winspool.h):

  • EscapeCode,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG) 值。

  • PageNumber,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG) 值。

DOCUMENTEVENT_XPS_ADDFIXEDPAGEPOST
与 DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRE 相同。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPRE
pvIn 指向包含四个属性的 PrintPropertiesCollection 结构(请参阅 Winspool.h):

  • EscapeCode,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG)。 EscapeCode 是事件值。

  • JobIdentifier,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG) 值。

  • JobName,它是 EPrintPropertyType:: kPropertyTypeString (UNICODE) 值。

  • PrintTicket,它是一个 EPrintPropertyType:: kPropertyTypeByte 值。

必须在“PRE”事件中分配 PrintPropertiesCollection 结构及其属性,并在相应的“POST”事件中将其释放。 可以将 pvOut 设置为 NULL,以表示支持该事件,但对更改给定文档或页面的 PrintTicket 不感兴趣。 插件不应在“PRE”和“POST”事件之间卸载。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPOS
pvIn 与 DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPRE 中的 pvOut 指针相同

驱动程序必须释放 pvIn

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRINTTICKETPRE
pvIn 指向包含三个属性的 PrintPropertiesCollection 结构(请参阅 Winspool.h):

  • EscapeCode,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG) 值。 EscapeCode 是事件值。

  • DocumentNumber,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG) 值。

  • PrintTicket,它是一个 EPrintPropertyType:: kPropertyTypeByte 值。

必须在“PRE”事件中分配 PrintPropertiesCollection 结构及其属性,并在相应的“POST”事件中将其释放。 可以将 pvOut 设置为 NULL,以表示支持该事件,但对更改给定文档或页面的 PrintTicket 不感兴趣。 插件不应在“PRE”和“POST”事件之间卸载。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRINTTICKETPOS
pvIn 与 DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRINTTICKETPRE 中的 pvOut 指针相同。

驱动程序必须释放 pvIn

DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRINTTICKETPRE
pvIn 指向包含三个属性的 PrintPropertiesCollection 结构(请参阅 Winspool.h):

  • EscapeCode,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG) 值。 EscapeCode 是事件值。

  • PageNumber,它是一个 EPrintPropertyType::kPropertyTypeInt32 (ULONG)。

  • PrintTicket,它是一个 EPrintPropertyType:: kPropertyTypeByte。

必须在“PRE”事件中分配 PrintPropertiesCollection 结构及其属性,并在相应的“POST”事件中将其释放。 可以将 pvOut 设置为 NULL,以表示支持该事件,但对更改给定文档或页面的 PrintTicket 不感兴趣。 插件不应在“PRE”和“POST”事件之间卸载。

DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRINTTICKETPOS
pvIn 与 DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRINTTICKETPRE 中的 pvOut 指针相同。

驱动程序必须释放 pvIn

DOCUMENTEVENT_XPS_CANCELJOB
pvInNULL

cbOut
如果 iEsc 参数包含 DOCUMENTEVENT_QUERYFILTER,WPF 打印支持将提供 pvOut 参数在 cbOut 参数中引用的缓冲区大小。 对于 iEsc 的所有其他值,不使用 cbOut

pvOut
指向 WPF 打印支持提供的缓冲区的指针。 缓冲区的大小和内容取决于 iEsc 参数的值。 下面列出了每个 iEsc 值的 pvOut 缓冲区内容。

DOCUMENTEVENT_QUERYFILTER
调用方提供的指向包含 DOCEVENT_FILTER 结构的缓冲区的指针。

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPRE
指向 PrintPropertiesCollection 结构(请参阅 Winspool.h)的指针,该结构包含 EPrintPropertyType::kPropertyTypeBuffer 类型的“PrintTicket”属性。 此属性始终存在。 没有 PrintTicket 时,PrintPropertyValue.propertyBlob.pBuf 的值为 NULL

该属性包含 XML PrintTicket,Microsoft Windows Presentation Foundation (WPF) 将从中使用 PrintTicket,而不是 XPSDocumentWriter 调用方提供的 PrintTicket。 (如果 pvOutNULL 或属性不存在,或者属性数据为 NULL,则 WPF 将使用调用方提供的 PrintTicket。)

处理完该事件后,WPF 将调用 DocumentEvent 和 DOCUMENTEVENT_XPS_ADFIXEDDOCUMENTSEQUENCEPRINTTICKETPOST,以便驱动程序释放 pvOut

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPOS
NULL

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRINTTICKETPRE
指向 PrintPropertiesCollection 结构(请参阅 Winspool.h)的指针,该结构包含 EPrintPropertyType::PropertyTypeBuffer 类型的“PrintTicket”属性。 此属性始终存在。 没有 PrintTicket 时,PrintPropertyValue.propertyBlob.pBuf 的值为 NULL

该属性包含 XML PrintTicket,WPF 将从中使用 PrintTicket,而不是 XPSDocumentWriter 调用方提供的 PrintTicket。 (如果 pvOutNULL 或属性不存在,或者属性数据为 NULL,则 WPF 将使用调用方提供的 PrintTicket。)

处理完该事件后,WPF 将调用 DocumentEvent 和 DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRINTTICKETPOST,以便驱动程序释放 pvOut

DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRINTTICKETPOS
NULL

DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRINTTICKETPRE
指向 PrintPropertiesCollection 结构(请参阅 Winspool.h)的指针,该结构包含 EPrintPropertyType:: PropertyTypeBuffer 类型的“PrintTicket”属性。 此属性始终存在。 没有 PrintTicket 时,PrintPropertyValue.propertyBlob.pBuf 的值为 NULL

该属性包含 XML PrintTicket,WPF 将从中使用 PrintTicket,而不是 XPSDocumentWriter 调用方提供的 PrintTicket。 (如果 pvOutNULL 或属性不存在,或者属性数据为 NULL,则 WPF 将使用调用方提供的 PrintTicket。)

处理完该事件后,WPF 将调用 DocumentEvent 和 DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRINTTICKETPOST,以便驱动程序释放 pvOut

DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRINTTICKETPOS
NULL

返回值

DrvDocumentEvent 会返回以下值之一:

DOCUMENTEVENT_SUCCESS
驱动程序成功处理了 iEsc 识别的转义码。

DOCUMENTEVENT_FAILURE
驱动程序支持 iEsc 识别的转义码,但发生了故障。

DOCUMENTEVENT_UNSUPPORTED
驱动程序不支持 iEsc 识别的转义码。

XPS 文档事件结构和事件代码值

以下代码示例显示了新 XPS 文档事件使用的结构和常量。

//
// structures used in XPS Document events
//
 
typedef enum
    {
        kPropertyTypeString = 1,
        kPropertyTypeInt32,
        kPropertyTypeInt64,
        kPropertyTypeByte,
        kPropertyTypeTime,
        kPropertyTypeDevMode,
        kPropertyTypeSD,
        kPropertyTypeNotificationReply,
        kPropertyTypeNotificationOptions,

    } EPrintPropertyType;

    typedef struct
    {
        EPrintPropertyType       ePropertyType;
        union
        {
            BYTE                 propertyByte;
            PWSTR                propertyString;
            LONG                 propertyInt32;
            LONGLONG             propertyInt64;
            struct {
                DWORD  cbBuf;
                LPVOID pBuf;
            }                    propertyBlob;
        } value;

    }PrintPropertyValue;

    typedef struct
    {
        WCHAR*                  propertyName;
        PrintPropertyValue      propertyValue;

    }PrintNamedProperty;

    typedef struct
    {
        ULONG                   numberOfProperties;
        PrintNamedProperty*     propertiesCollection;

    }PrintPropertiesCollection;

前面代码示例中的结构在 Winspool.h 中定义。

Winddiui.h 中定义了以下转义码。

//
 // Escape code for XPS Document events
//
#define DOCUMENTEVENT_QUERYFILTER                                     14
#define DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRE                 1
// DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRE must have same value as //DOCUMENTEVENT_CREATEDCPRE for Winspool.drv to query the driver for supported events and reset the cached events.
#define DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRE                         2
#define DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRE        3                           
#define DOCUMENTEVENT_XPS_ADDFIXEDPAGEPOST                            4
#define DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPOST                        5
#define DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPOST                13
// DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPOST must have same value as //DOCUMENTEVENT_STARTDOCPOST for Winspool.drv to signal the tray balloon that //the document is completed
#define DOCUMENTEVENT_XPS_CANCELJOB                                   6
#define DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPRE      7
#define DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRINTTICKETPRE              8
#define DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRINTTICKETPRE                  9
#define DOCUMENTEVENT_XPS_ADDFIXEDPAGEPRINTTICKETPOST                 10
#define DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTPRINTTICKETPOST             11
#define DOCUMENTEVENT_XPS_ADDFIXEDDOCUMENTSEQUENCEPRINTTICKETPOST     12