当您的应用程序必须处理专业打印设备(具有不能由现有的 PrintSystemObject、PrintQueue、PrintCapabilities 和 PrintTicket 类反映的特性)时,您可能希望通过继承来派生新类,创建 PrintCapabilities 和 PrintTicket 类的扩展版本,还可能希望扩展Print Schema。本文介绍此类项目的主要部分,但仅描述众多扩展相关托管类的方法之一。
我们建议您结合Print Schema的详尽文档来阅读本文。本文假定您对什么是架构以及什么是 PrintTicket 文档和 PrintCapabilities 文档有基本的了解。
本文包含以下部分。
通过继承派生新类
确定在打印架构中是否已定义设备的功能
创建用于表示设备功能的类型
扩展 PrintCapabilities 和 PrintTicket 类
扩展 PrintTicket 类
扩展 PrintCapabilities 类
读取和写入 PrintCapabilities 和 PrintTicket XML 流
重载和扩展属性及方法
扩展架构定义的功能
扩展 System.Printing.IndexedProperties 命名空间
示例
本文中介绍的示例项目并不提供编译和运行应用程序所需的全部详细信息。它只是针对那些具有 System.Printing 和 System.Printing.IndexedProperties 命名空间未显式支持的功能的打印设备,大致介绍扩展这些命名空间的功能的主要步骤。只有在需要具体详细信息时才提供代码示例。
另外,代码示例也并不一定包括很好的编程技巧或安全代码。与本文主题无直接关系的所有内容都已被省略。
最后一点,本文主要面向应用程序开发人员而不是设备驱动程序开发人员。因此,重点是编写 PrintTicket 对象,而不是 PrintCapabilities 对象。
通过继承派生新类
首先从 PrintQueue 类派生一个表示设备的类。在下面的代码示例中,BrailleEmbosser 类是派生的。Braille 是一种盲人可读的语言,因为这种语言的符号是由从纸面凸起的“点”组成,这样盲人就可以用指尖感觉得到。Braille embosser 只是一个可以打印 Braille 的打印机。Braille embosser 的某些驱动程序可以将常规 Braille 转换为 Braille Grade 3(有时也称为 Braille 3),后者是使用许多缩约形式和简写形式的 Braille,可以节省空间。本示例提供一个属性来表示此功能。
通常,您还需要重载某些继承的属性和方法。有关详细信息,请参见下面的重载和扩展属性及方法。
class BrailleEmbosser : PrintQueue
{
public BrailleEmbosser(PrintServer ps, String s, PrintSystemDesiredAccess access) : base(ps, s, access)
{
// Optionally, include here code to set non-inherited fields.}
// other constructor declarations omitted
private Boolean isBraille3Enabled;
public Boolean IsBraile3Enabled
{
get { return isBraille3Enabled; }
set { isBraille3Enabled = value; }
}
// remainder of class definition omitted
}
确定在打印架构中是否已定义设备的功能
PrintTicket 和 PrintCapabilities 类具有表示最通用的打印机功能的属性,但Print Schema Public Keywords规范中定义的许多功能都未在这些类中显式反映出来(要查看通用功能的列表,只需查看 PrintCapabilities 类的属性即可)。您应阅读此规范以确定其中是否定义了设备的特殊功能。对于此规范中包括 的任何功能,使用此规范的模型都大有好处:它的通用模型和术语使得为一个设备创建的 PrintTicket XML 文档也可以用于另一个设备(第二个设备可能是由另一家制造商生产;它可能是在最初创建 PrintTicket 文档之后 设计的)。Print Ticket 可以嵌入到文档本身,这样当文档分发给具有不同打印机的其他人时,作者的打印意图以及格式意图可以一并传达过去。
在本文的其余部分,PrintTicket 和 PrintCapabilities 类显式支持的功能称为“通用功能”。那些Print Schema Public Keywords规范中已定义、但是这两个类不显式支持的功能称为“已定义的功能”。未在“公共关键字”规范中定义的功能称为“新功能”。
也可能存在这种一种情况:您的设备具有一个与已定义的功能几乎完全一致的功能,但它有一个或多个在Print Schema Public Keywords规范中不被识别的额外选项。Print Schema可以扩展以处理类似功能,方式是利用尽可能多的现有定义。有关如何处理此类功能的更多信息,请参见下面的扩展架构定义的功能。
创建用于表示设备功能的类型
与打印机功能对应的 PrintTicket 和 PrintCapabilities 属性采用特殊类型,通常为表示一个功能的枚举及其可能值。例如,Collation 枚举是 PrintTicket.Collation 属性的类型。另外,作为 PrintCapabilities.CollationCapability 属性的类型的集合的成员也具有此类型。
使用这些现有类作为模型为设备的已定义功能和新功能创建类。在下面的代码示例中,声明了 BrailleGrade3 枚举。它构造于 Collation 枚举的模型之上,因为 Grade 3 转换与逐份打印类似:任何打印机都必须支持至少一种输出类型(逐份打印或非逐份打印),因为它们是互斥的。有些打印机对这两种类型都支持(仅支持逐份打印输出的打印机很少见,但也要将这种可能性考虑进去)。因此,可以有仅支持未转换的 Braille 输出、仅支持转换后的输出(可能性不大)和这两者都支持的 Embosser。由于 Collation 处理 PrintTicket 文档生成应用程序将逐份打印功能设置为Print Schema Public Keywords规范不识别的值这种一种情况,因此 BrailleGrade3 枚举包括一个 Unknown 值。如果您的应用程序使用此类文档来创建 PrintTicket 对象,则 PrintTicket.Collation 属性将获得值 Unknown(PrintCapabilities 对象从不使用 Unknown 值)。
public enum BrailleGrade3 { Translated, Untranslated, Unknown }
枚举并非总是表示功能的最佳方法。有时,使用引用类型类更好。当功能具有一个从属部分(每个部分都有自己的值)的嵌套结构时,使用引用类型类的优势更明显。例如,PageMediaSize 类具有 Height 和 Width 属性。PageMediaSize 是 PrintTicket.PageMediaSize 属性的类型。另外,作为 PrintCapabilities.PageMediaSizeCapability 属性的类型的集合的成员也具有此类型。
扩展 PrintCapabilities 和 PrintTicket 类
尽管 PrintTicket 和 PrintCapabilities 类不能继承,但您可以扩展Print Schema来识别已定义的功能和新功能。
扩展 PrintTicket 类
要将 PrintTicket 类与扩展的功能系统一起使用,请执行以下步骤。下面给出了一些详细信息。
扩展 PrintTicket 类的高级别过程
如果设备具有新功能,则创建一个新的类来封装这些新功能(有关详细信息,请参见创建 NewFeaturesPrintTicket 类)。
如果设备具有已定义的功能,则创建一个类来封装这些已定义的功能(有关详细信息,请参见创建 DefinedFeaturesPrintTicket 类)。
创建一个类来表示整个 Print Ticket。如果设备没有已定义的功能或新功能,那么此类在应用程序中的作用与 PrintTicket 类相同(有关详细信息,请参见创建 WholePrintTicket 类)。
创建 NewFeaturesPrintTicket 类的过程
如果设备具有新功能,则声明一个类来封装这些功能。将该类命名为 NewFeaturesPrintTicket。
为新类指定属性以表示设备的新功能。通常,每个属性均属于您创建的类型(通常是一个枚举)。请参见上面的创建用于表示设备功能的类型。
为新类指定一个附加属性,并将它命名为 PrivateNamespace,它将包含对定义设备的新功能的私有 XML 命名空间的引用。当将 XML 标记写入 PrintCapabilities 和 PrintTicket 文档时,您将需要此字符串。请参见下面的读取和写入 PrintCapabilities 和 PrintTicket XML 流。
为该类指定两个构造函数。构造函数应该在 PrintTicket 的两个构造函数上建模。一个没有参数,另一个采用带有 XML 内容的 Stream 对象。XML 流将是定义新功能(而不是通用功能)的 PrintTicket 文档(请参见Print Schema-Related Technologies和 PrintTicket Schema and Document Construction)。具有参数的构造函数将对 PrintTicket 类的单参数构造函数的模式引发异常。
为该类创建一个 GetXmlStream 和一个 SaveTo 方法。对这两个方法均使用访问关键字“internal”。这旨在匹配具有这些名称的 PrintTicket 方法的功能,但它们将处理定义新功能而不是通用功能的 PrintTicket 文档。这些方法必须确保它们所生成的流在开始 <PrintTicket … > 元素中具有额外的命名空间声明(PrivateNamespace 属性的值)。请参见下面的读取和写入 PrintCapabilities 和 PrintTicket XML 流。
创建 DefinedFeaturesPrintTicket 类的过程
如果设备具有已定义的功能,则声明一个类来封装这些功能。将它命名为 DefinedFeaturesPrintTicket。它的构造方式应该与上面构造 NewFeaturesPrintTicket 的方式一样,但有以下例外。
类的属性必须具有与Print Schema Public Keywords规范中对应的功能名称相匹配的名称。
不要创建 PrivateNamespace 属性。已定义的功能的命名空间与通用功能一样。请参见下面的读取和写入 PrintCapabilities 和 PrintTicket XML 流。
GetXmlStream 和 SaveTo 方法不生成带有额外命名空间声明的流。
创建 WholePrintTicket 类的过程
声明一个表示整个 Print Ticket 的类,这样,如果设备没有已定义的功能或新功能,则该类在应用程序中所起的作用将与 PrintTicket 类相同。将该类命名为 WholePrintTicket。
为 WholePrintTicket 指定一个 PrintTicket 类型的属性,并将它命名为 CommonFeatures。
为 WholePrintTicket 指定下面两个附加属性中的一个或全部两个,具体取决于该类具有新功能、已定义的功能还是两者均具备。
类型为 NewFeaturesPrintTicket 的 NewFeatures。
类型为 DefinedFeaturesPrintTicket 的 DefinedFeatures。
为 WholePrintTicket 指定两个构造函数。一个构造函数没有参数,另一个构造函数采用带有 XML 内容的 Stream 对象。带参数的构造函数将执行以下操作。
为由 CommonFeatures 属性引用的 PrintTicket 对象的构造函数传递 Stream。该构造函数将完全忽略 Stream 中与通用功能不相关的任何标记。
为由 NewFeatures 属性引用的 NewFeaturesPrintTicket 对象的构造函数传递 Stream。该构造函数将完全忽略 Stream 中与新功能不相关的任何标记。如果有任何新功能标记,则 Stream 将以 <psf:PrintTicket xmlns:psf="https://schemas.microsoft.com/windows/2003/08/printing/printschemaframework" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1" xmlns:命名空间缩写=命名空间的完整名称> 开头,其中命名空间的完整名称 是一个 URL,用于标识定义新功能的架构,命名空间缩写 是该完整名称的缩写(有关更多信息,请参见下面的读取和写入 PrintCapabilities 和 PrintTicket XML 流)。
为由 DefinedFeatures 属性引用的 DefinedFeaturesPrintTicket 对象的构造函数传递 Stream。该构造函数将完全忽略 Stream 中与已定义的功能不相关的任意标记。
为该类创建一个 GetXmlStream 和一个 SaveTo 方法。这些方法旨在匹配具有这些名称的 PrintTicket 方法的功能。它们应具有下列特征。
上述每个方法都应调用由 CommonFeatures 属性、DefinedFeatures 属性(如果有)和 NewFeatures 属性(如果有)引用的对象中具有相同名称的对应方法。
每个方法都应连接上一条中描述的调用所生成的流。当然,应删除除最后一个 </PrintTicket> 结束标记以外的所有该标记,以及除第一个 <PrintTicket … > 开始标记以外的所有该标记。除非没有新功能,否则开始标记应具有额外的命名空间声明(请参见步骤 4b)。为此,您应当考虑始终令新功能流(如果有)成为连接流中的第一个流,因为它在自己的 <PrintTicket … > 开始标记中已有该声明。
为了实现此连接,WholePrintTicket 的 GetXmlStream 和 SaveTo 方法将需要首先工作在一个临时流的内部。具体地说,它们将具有三个不同的类,每个类都将其内容序列化到该临时流中,执行连接工作(和删除工作 – 请参见下一条),然后将连接结果输出到最终输出流。
在连接后,WholePrintTicket 的 GetXmlStream 和 SaveTo 方法在返回最终流前还必须从流中移除元素的二重副本和三重副本。这些二重和三重条目将位于流中,因为三个对象 PrintTicket、NewFeaturesPrintTicket 和 DefinedFeaturesPrintTicket 中的每一个都保留用于构造流的原始 PrintTicket 文档的完整形式,即使它们在其属性中仅公开文档的一部分也是如此。
如果您的 WholePrintTicket(Stream) 构造函数(请参见上面)通过为通用、新的和已定义的标记元素分别创建流,而将传入的流分成三个部分,那么您将不必执行上一条中所介绍的删除步骤。之后,上述每个较小的流都将传递到 WholePrintTicket 的三个属性的相应构造函数。要使用此方法,您必须向三个流中的每一个均添加一个结束 </PrintTicket> 标记。对于 CommonFeatures 和 DefinedFeatures 属性的流,应添加一个类似于如下所示的开始标记:<psf:PrintTicket xmlns:psf="https://schemas.microsoft.com/windows/2003/08/printing/printschemaframework" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1">。NewFeatures 属性的构造函数的开始标记将添加一个类似于如下所示的附加私有命名空间:<psf:PrintTicket xmlns:psf="https://schemas.microsoft.com/windows/2003/08/printing/printschemaframework" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1" xmlns:命名空间缩写=命名空间的完整名称>,其中命名空间的完整名称 是一个 URL,用于标识定义新功能的架构,命名空间缩写 是该完整名称的缩写。
下面的代码示例显示当应用于 Braille embosser 示例时,此过程的部分输出结果(为了节省空间和简单起见,省略了许多内容)。请注意,BrailleGrade3 属性是 Nullable<T> 类型。这遵循 PrintTicket 的属性(如 Collation)的模式。此示例假设既有新功能也有已定义的功能,但未指定任何特定的已定义功能。
class NewFeaturesPrintTicket
{
public NewFeaturesPrintTicket()
{
// Optionally, initialize fields.For example:
privateNamespace = "http://www.AjaxEmbossers.com/schemas/deluxemodels/v.1.0";
}
public NewFeaturesPrintTicket(Stream printTicketDocument)
{
// Parse the stream and initialize fields representing features here.// Optionally, initialize other fields.For example:
privateNamespace = "http://www.AjaxEmbossers.com/schemas/deluxemodels/v.1.0";
}
private Nullable<BrailleGrade3> brailleGrade3;
public Nullable<BrailleGrade3> BrailleGrade3
{
get { return brailleGrade3; }
set { brailleGrade3 = value;}
}
private String privateNamespace;
public String PrivateNamespace
{
get { return privateNamespace; }
set { privateNamespace = value; }
}
}
class DefinedFeaturesPrintTicket
{
// Details omitted.Use the NewFeaturesPrintTicket
// as a model, but leave out the privateNamespace field
// and property.}
class WholePrintTicket
{
public WholePrintTicket()
{
commonFeatures = new PrintTicket();
newFeatures = new NewFeaturesPrintTicket();
definedFeatures = new DefinedFeaturesPrintTicket();
}
public WholePrintTicket(Stream wholePrintTicket)
{
// Method 1: Pass the stream to the three constructors.// Be sure to reset the read-write position of the stream
// to the beginning of the stream after each call to a
// constructor.// commonFeatures = new PrintTicket(wholePrintTicket);
// reset read-write head here
// newFeatures = new NewFeaturesPrintTicket(wholePrintTicket);
// reset read-write head here
// definedFeatures = new DefinedFeaturesPrintTicket(wholePrintTicket);
// reset read-write head here
// Method 2: Parse the stream and split it into three streams.// Then pass them to the constructors of the three properties.// commonFeatures = new PrintTicket(commonFeaturesPrintTicketDocument);
// newFeatures = new NewFeaturesPrintTicket(newFeaturesPrintTicketDocument);
// definedFeatures = new DefinedFeaturesPrintTicket(definedFeaturesPrintTicketDocument);
}
private PrintTicket commonFeatures;
public PrintTicket CommonFeatures
{
get { return commonFeatures; }
set { commonFeatures = value;}
}
private PrintTicket newFeatures;
public PrintTicket NewFeatures
{ // Details omitted.See CommonFeatures above.}
private PrintTicket definedFeatures;
public PrintTicket DefinedFeatures
{ // Details omitted.See CommonFeatures above.}
}
扩展 PrintCapabilities 类
要在您的设备中使用 PrintCapabilities 类,您需要像扩展 PrintTicket 类那样来扩展该类。由于您可以将 PrintTicket 的扩展用作一个模型,因此下面仅提供简短的概述。
创建三个新类,一个用于封装新功能 (NewFeaturesPrintCapabilities),一个用于封装已定义的功能 (DefinedFeaturesPrintCapabilities),一个用于表示整个 PrintCapabilities 文档 (WholePrintCapabilities)。
前两个新类的属性的类型通常为 ReadOnlyCollection<T>。使用 PrintCapabilities 的现有属性(如 CollationCapability)作为模型。
另外,根据现有 PrintCapabilities 类的模式,属性名称的末尾应当有“Capability”;例如,BrailleGrade3Capability。
NewFeaturesPrintCapabilities 类将有一个与您为 NewFeaturesPrintTicket 创建的 PrivateNamespace 属性完全相同的属性。
上述类所具有的方法都是从 Object 类继承来的。
DefinedFeaturesPrintCapabilities 构造函数在使用 Stream 来初始化属性前,必须先验证传递给它的 Stream 是否符合Print Schema Framework(执行此操作的一种简单方法是将 Stream 首先传递给 PrintCapabilities 构造函数。如果后者没有引发任何异常,即说明流有效)。
NewFeaturesPrintCapabilities 构造函数在使用 Stream 来初始化属性前,必须先验证传递给它的 Stream 是否符合私有命名空间。
DefinedFeaturesPrintCapabilities 和 NewFeaturesPrintCapabilities 构造函数都将在现有 PrintCapabilities 构造函数的模式上引发异常。
WholePrintCapabilities 类将有 CommonFeatures、DefinedFeatures 和 NewFeatures 属性。这些属性的类型将分别为 PrintCapabilities、DefinedFeaturesPrintCapabilities 和 NewFeaturesPrintCapabilties。每个类型都构造于 WholePrintTicket 的属性的模式之上。
WholePrintCapabilities 类的构造函数将采用一个 Stream 参数,该参数表示整个 PrintCapabilities 文档。此构造函数应当将输入的整个 Stream 传递给它的成员属性的全部三个构造函数。由于 WholePrintCapabilities 类没有任何方法以 XML 格式导出其设置(类似于 WholePrintTicket 的 GetXmlStream 和 SaveTo 方法),因此三个属性内有二重或三重标记并无妨碍。
有关附加信息,请参见PrintCapabilities Schema and Document Construction。
读取和写入 PrintCapabilities 和 PrintTicket XML 流
现有 PrintTicket 和 PrintCapabilities 类以及在前面的扩展 PrintCapabilities 和 PrintTicket 类中创建的新类的构造函数和方法的主要任务是:读取、分析、写入和(有时)验证内容为 PrintTicket 文档或 PrintCapabilities 文档的 Stream 对象。您应该熟悉基本的文件 I/O 以及这些类的方法。由于这些流的内容为 XML,因此您还应熟悉 .NET Framework 中的 XML 处理选项中说明的 XML 读取和写入支持。如果您的应用程序处理的是 XML 纸张规范 (XPS) 文档,则在 System.Windows.Xps、System.Windows.Xps.Packaging 和 System.Windows.Xps.Serialization 命名空间中存在设计用于读取和写入 XPS 文档(包括读取和写入 PrintTicket)的 API。有关将与 PrintTicket 的关系添加到包的信息,另请参见 PackageRelationship。
您可以在 PrintTicket Example和 PrintCapabilities Document Example中找到 PrintTicket 文档和 PrintCapabilities 文档的完整示例。
下面是 PrintCapabilities 文档的一个简单示例,在此示例中仅考虑了设备的一项功能,其他所有功能均忽略。显示的功能为 DocumentCollate,它是由 PrintCapabilities.CollationCapability 和 PrintTicket.Collation 属性表示的功能。
<psf:PrintCapabilities xmlns:psf="https://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1">
<!-- other features omitted -->
<psf:Feature name="psk:DocumentCollate">
<psf:Property name="psf:SelectionType">
<psf:Value xsi:type="xsd:QName">psk:PickOne</psf:Value>
</psf:Property>
<psf:Property name="psk:DisplayName">
<psf:Value xsi:type="xsd:string">Collate Copies</psf:Value>
</psf:Property>
<psf:Option name="psk:Collated" constrained="psk:None">
<psf:Property name="psk:DisplayName">
<psf:Value xsi:type="xsd:string">Yes</psf:Value>
</psf:Property>
</psf:Option>
<psf:Option name="psk:Uncollated" constrained="psk:None">
<psf:Property name="psk:DisplayName">
<psf:Value xsi:type="xsd:string">No</psf:Value>
</psf:Property>
</psf:Option>
</psf:Feature>
<!-- other features omitted -->
</PrintCapabilities>
请注意,功能的每个可能选项(collated 和 uncollated)都已列出,并且每个选项的状态(即,是否受约束)都已标识。在完整的 PrintCapabilities 文档中,每个功能的每个选项的状态都标识出来,因此该文档是设备配置的一种快照形式。
下面是仅有一个功能的 PrintTicket 文档的简单示例。
<psf:PrintTicket xmlns:psf="https://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" version="1">
<!-- other features omitted -->
<psf:Feature name="psk:DocumentCollate">
<psf:Option name="psk:Collated" />
</psf:Feature>
<!-- other features omitted -->
</PrintTicket>
请注意,结构可以再稍微简单一些,因为对于 PrintTicket 文档来说,显式指定每个选项的状态不是必需的。它只需要标识所请求的选项。
此功能的语法和结构是在 DocumentCollate 中通过Print Schema Framework和Print Schema Public Keywords定义的。当您处理新功能时,将会处理在补充架构中定义的私有 XML 命名空间中定义的功能。通常,这是由设备的制造商、行业协会或非盈利性的标准组织提供的;但创建人可能是您。可使用现有的Print Schema Framework和Print Schema Public Keywords来了解必需的语法以及查找您的定义可基于的模型。Microsoft 自己创建了一个新的命名空间,以便将 PrintCapabilities 和 PrintTicket 系统扩展到新的 Microsoft XPS Document Writer (MXDW) 驱动程序。有关详细信息,请参见 MXDW 配置设置。
如果我们假设一个名为 Ajax Embosser 的虚拟公司,它用与 Microsoft 定义文档逐份打印功能类似的方式定义 BrailleGrade3 转换功能,这样,我们可以看到此功能的 PrintCapabilities 和 PrintTicket 文档条目的外观。请注意,必须在 <PrintCapabilities … > 和 <PrintTicket … > 开始标记中声明定义该功能的命名空间。
PrintCapabilities 文档标记
<psf:PrintCapabilities xmlns:psf="https://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ajax="http://www.AjaxEmbossers.com/schemas/deluxemodels" version="1">
<!-- other features omitted -->
<psf:Feature name="ajax:BrailleGrade3Translation">
<psf:Property name="psf:SelectionType">
<psf:Value xsi:type="xsd:QName">psk:PickOne</psf:Value>
</psf:Property>
<psf:Property name="psk:DisplayName">
<psf:Value xsi:type="xsd:string">Braille3 translation</psf:Value>
</psf:Property>
<psf:Option name="ajax:Translated" constrained="psk:None">
<psf:Property name="psk:DisplayName">
<psf:Value xsi:type="xsd:string">Yes</psf:Value>
</psf:Property>
</psf:Option>
<psf:Option name="ajax:Untranslated" constrained="psk:None">
<psf:Property name="psk:DisplayName">
<psf:Value xsi:type="xsd:string">No</psf:Value>
</psf:Property>
</psf:Option>
</psf:Feature>
<!-- other features omitted -->
</PrintCapabilities>
PrintTicket 文档标记
<psf:PrintTicket xmlns:psf="https://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ajax="http://www.AjaxEmbossers.com/schemas/deluxemodels" version="1">
<!-- other features omitted -->
<psf:Feature name="ajax:BrailleGrade3Translation">
<psf:Option name="ajax:Translated" />
</psf:Feature>
<!-- other features omitted -->
</PrintTicket>
有关编写处理新功能的 PrintTicket 文档的更多信息,请参见Creating a Device-Specific PrintTicket。有关创建 PrintTicket 和 PrintCapabilities 文档的详尽文档,请参见“打印架构”文档的“PrintCapabilities Schema and Document Construction”和“PrintTicket Schema and Document Construction”部分。
重载和扩展属性及方法
具有 PrintTicket 参数或返回 PrintTicket 以及您希望与扩展的功能系统一起使用的任何类的任何方法,都必须由使用 WholePrintTicket 来代替 PrintTicket 的方法所取代。类似地,您希望使用的类型 PrintTicket 的任何属性将必须替换为类型 WholePrintTicket 的属性。同样,PrintCapabilities 和 WholePrintCapabilities 也是如此(进行相应的修改)。
当承载方法或属性的类是可继承的,您可以派生类并重载方法或属性以使用 WholePrintTicket,而不使用 PrintTicket。
如果承载类不是可继承的,则需要按照上面扩展 PrintTicket 和 PrintCapabilities 的方法来扩展它:创建一个类,使该承载类作为它的成员。然后,为外部类方法和属性指定与具有(或返回)PrintTicket 或 PrintCapabilities 参数的相应方法一致的名称。通常,外部类应当与同名的内部类的功能匹配,但它将使用 WholePrintTicket 或 WholePrintCapabilities 参数,而不使用 PrintTicket 或 PrintCapabilities 参数。另外,对于类型为 PrintTicket 或 PrintCapabilities 的内部类属性,请在使用 WholePrintTicket 或 WholePrintCapabilities 的外部类中创建同名的相应属性。
您需要重载的两个最重要的方法可能是 MergeAndValidatePrintTicket 的两个版本。BrailleEmbosser 类(请参见上面的通过继承派生新类)需要这样的替代项:使用 WholePrintTicket 参数,并添加对照私有命名空间的架构验证具有新功能的票证的逻辑。您可以重载现有的方法,也可以创建名为 MergeAndValidateWholePrintTicket 的新方法。
返回 PrintTicket 的两个方法是 ConvertDevModeToPrintTicket 和 Clone。在 .NET Framework 中还有其他 15 种方法(不包括重载)采用一个 PrintTicket 参数和 19 个类型为 PrintTicket 的属性。但是任何给定的应用程序都不太可能使用其中较多的方法,所以不要因为看到这些数字而担心您的工作量太大。令人高兴的是,返回 PrintCapabilities 对象的唯一方法为 GetPrintCapabilities,没有类型为 PrintCapabilities 的属性。
扩展架构定义的功能
新功能并非是导致需要扩展Print Schema的唯一原因。当设备为熟悉的已定义功能提供新的、未定义的选项时,也需要进行扩展。由于私有命名空间必须用于新的未定义选项(就像它必须用于全新的功能一样),因此将上述扩展功能视为全新功能可能较为容易一些(但是对该功能及其已定义的选项使用架构定义的名称),也就是说,可以将其归入 NewFeaturesPrintTicket 和 NewFeaturesPrintCapabilities 中。讨论实现此类架构扩展所需的全部详细信息超出了本文的范畴,不过,请注意,必须由 WholePrintTicket.GetXmlStream 和 WholePrintTicket.SaveAs 方法完成的连接工作可能更为复杂一些。
扩展 System.Printing.IndexedProperties 命名空间
如果您希望充分利用 System.Printing.IndexedProperties 命名空间中的 API,可能需要从 PrintProperty 派生一个新类。如果您为从 PrintQueue 派生的类所创建的属性不具有由 System.Printing.IndexedProperties 中的任何现有类所表示的类型,您将需要执行此操作。有关可以利用 System.Printing.IndexedProperties 命名空间执行的操作的示例,请参见如何:克隆打印机和如何:在不使用反射的情况下获得打印系统对象属性。
对于上面的示例,此步骤是不必要的,因为只向 BrailleEmbosser 类添加了一个属性 IsBraile3Enabled,它是 Boolean。已经有一个 System.Printing.IndexedProperties.PrintBooleanProperty 类。
请参见
任务
参考
System.Printing.IndexedProperties
System.Windows.Xps.Serialization