HOW TO:擴充列印結構描述和建立新的列印系統類別
當您的應用程式必須處理特殊列印裝置,而現有的 PrintSystemObject、PrintQueue、PrintCapabilities 和 PrintTicket 等類別並無法反映這些裝置的特性時,您可能必須透過繼承的方式來衍生新類別、建立 PrintCapabilities 和 PrintTicket 類別的延伸版本,而且可能還必須擴充Print Schema。本文說明這類專案的主要部分;但是文中說明的只是多種擴充相關 Managed 類別之方法的其中一種。
建議您同時參閱本文以及Print Schema的完整文件。本文假設您至少對結構描述、PrintTicket 文件與 PrintCapabilities 文件都有基本的了解。
本文包含下列各節:
以繼承方式衍生新類別
判斷是否已在列印結構描述中定義裝置的功能
建立用來表示裝置功能的型別
擴充 PrintCapabilities 和 PrintTicket 類別
擴充 PrintTicket 類別
擴充 PrintCapabilities 類別
讀取及寫入 PrintCapabilities 和 PrintTicket XML 資料流
多載及擴充屬性和方法
擴展結構描述定義的功能
擴充 System.Printing.IndexedProperties 命名空間
範例
本文顯示的範例專案並未提供編譯及執行應用程式時所需的所有詳細資料。這個範例專案只提供了主要的執行步驟,目的是要讓您大致了解如何擴充 System.Printing 和 System.Printing.IndexedProperties 命名空間的功能,以支援這些命名空間未明確支援其功能的列印裝置。因此,只有在需要具體的詳細資料時,才會提供程式碼範例。
此外,這些程式碼範例不一定包含良好的程式設計實作或安全程式碼;它會省略任何與本文主題無直接關聯的部分。
最後,本文的目標閱者為應用程式開發人員,而非裝置驅動程式開發人員,因此重點會在撰寫 PrintTicket 物件,而不是 PrintCapabilities 物件。
以繼承方式衍生新類別
一開始請先利用 PrintQueue 類別,衍生一個用來表示裝置的類別。下列程式碼範例中衍生的是 BrailleEmbosser 類別。點字是盲人可讀的一種語言,因為點字符號是由紙張表面凸起的「點」所組成,所以可以利用手指觸摸來讀取這些符號。點字印表機就是用來列印點字的印表機。某些點字印表機驅動程式可以將一般的點字轉譯成 Braille Grade 3 (又稱為 Braille 3),也就是大量使用簡寫以及縮寫以節省空間的點字版本。此範例也提供表示這項功能的屬性。
通常,您還必須多載某些已經繼承的屬性和方法。如需詳細資訊,請參閱本文稍後的多載及擴充屬性和方法。
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 文件建立「之後」才設計製造的產品)。列印票證可以內嵌在文件本身,因此,就算將文件散發給擁有不同印表機的人,還是能夠實現作者想要達到的列印效果以及想要呈現的格式。
本文其餘內容將 PrintTicket 和 PrintCapabilities 類別明確支援的功能稱為「常用功能」,Print Schema Public Keywords規格中已定義但這兩個類別未明確支援的功能稱為「已定義的功能」,而「Public 關鍵字」規格中未定義的功能則稱為「新功能」。
您的裝置也有可能有某項功能幾乎與已定義的功能完全相符,但卻多了一個或多個Print Schema Public Keywords規格無法辨認的選項。您可以擴充Print Schema來處理這樣的功能,而且擴充時可以盡量沿用現有的定義。如需如何處理這類功能的詳細資訊,請參閱本文稍後的擴展結構描述定義的功能。
建立用來表示裝置功能的型別
對應於印表機功能之 PrintTicket 和 PrintCapabilities 的屬性是採用特殊的型別,通常是用於表示功能及其可能值的列舉型別。例如,Collation 列舉型別是 PrintTicket.Collation 屬性的型別。它也是 PrintCapabilities.CollationCapability 屬性型別之集合成員的型別。
請使用這些現有的類別做為模型,為裝置的已定義功能和新功能建立類別。下列程式碼範例中宣告了 BrailleGrade3 列舉型別。由於 Grade 3 的轉譯類似於定序,因此這個列舉型別是建構於 Collation 列舉型別的模型之上:任何印表機都必須支援至少一種輸出 (定序或非定序),因為這兩種輸出具有互斥 (Mutually Exclusive) 的關係。某些印表機同時支援這兩種輸出 (雖然只支援定序輸出的印表機很少,但還是必須考慮到這個可能性)。同樣地,也有點字印表機只支援未轉譯的點字輸出、只支援轉譯的輸出 (可能性不高),或是同時支援兩者。BrailleGrade3 列舉型別包含 Unknown 值的原因與 Collation 相同,都是為了處理 PrintTicket 文件產生應用程式已經將定序 (Collation) 功能設定為Print Schema Public Keywords規格無法辨認之值的情況。如果您的應用程式使用這類文件來建立 PrintTicket 物件,PrintTicket.Collation 屬性將會取得 Unknown 的值 (PrintCapabilities 物件絕不會使用 Unknown 值)。
public enum BrailleGrade3 { Translated, Untranslated, Unknown }
列舉型別並不一定是用來表示功能的最佳方法。有時參考型別 (Reference Type) 類別反而是比較好的選擇 (尤其是當功能具有從屬組件的巢狀結構,而這些組件各自擁有自己的值時)。例如,PageMediaSize 類別具有 Height 和 Width 屬性。PageMediaSize 是 PrintTicket.PageMediaSize 屬性的型別。它也是 PrintCapabilities.PageMediaSizeCapability 屬性型別之集合成員的型別。
擴充 PrintCapabilities 和 PrintTicket 類別
雖然您不能繼承 PrintTicket 和 PrintCapabilities 類別,但卻可以擴充Print Schema來辨識已定義的功能和新功能。
擴充 PrintTicket 類別
若要將 PrintTicket 類別與擴充的功能系統一起使用,請採用下列步驟 (以下僅列出部分細節):
擴充 PrintTicket 類別的高階程序
如果裝置擁有新功能,請建立新類別來封裝新功能 (請參閱<建立 NewFeaturesPrintTicket 類別>,以取得部分詳細資訊)。
如果裝置擁有已定義的功能,請建立類別來封裝已定義的功能 (請參閱<建立 DefinedFeaturesPrintTicket 類別>,以取得部分詳細資訊)。
建立用來代表完整列印票證的類別。這個類別在應用程式中扮演的角色,與裝置沒有已定義的功能或新功能時,PrintTicket 類別所扮演的角色相同 (請參閱<建立 WholePrintTicket 類別>,以取得部分詳細資訊)。
建立 NewFeaturesPrintTicket 類別的程序
如果裝置擁有新功能,請宣告類別來封裝這些功能。我們將這個類別稱為 NewFeaturesPrintTicket。
為您的新類別提供用來表示裝置新功能的屬性。一般而言,每個屬性都屬於您所建立的一種型別,通常是列舉型別。請參閱上面的建立用來表示裝置功能的型別。
為新類別提供另一個屬性 (我們將它稱為 PrivateNamespace),用以保存會定義裝置新功能之私用 (Private) 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 類別的程序
宣告代表完整列印票證的類別;此類別在應用程式中扮演的角色,與裝置沒有已定義的功能或新功能時,PrintTicket 類別所扮演的角色相同。我們將這個類別稱為 WholePrintTicket。
為 WholePrintTicket 提供屬性;我們將這個屬性稱為 CommonFeatures,其型別為 PrintTicket。
根據 WholePrintTicket 擁有的是新功能、已定義的功能或兩者都有,為其提供下列一或兩個額外屬性。
型別 NewFeaturesPrintTicket 的 NewFeatures。
型別 DefinedFeaturesPrintTicket 的 DefinedFeatures。
為 WholePrintTicket 提供兩個建構函式:一個不接受任何參數,另一個則接受具有 XML 內容的 Stream 物件。具有參數的建構函式將執行下列工作:
將 Stream 傳遞至 CommonFeatures 屬性所參考之 PrintTicket 物件的建構函式。該建構函式只會忽略 Stream 中與常用功能無關的任何標記。
將 Stream 傳遞至 NewFeatures 屬性所參考之 NewFeaturesPrintTicket 物件的建構函式。該建構函式只會忽略 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:namespace-abbreviation=full-namespace-name>,其中 full-namespace-name 是用來識別會定義新功能之結構描述的 URL,而 namespace-abbreviation 則是這個 URL 的縮寫 (如需詳細資訊,請參閱下面的讀取及寫入 PrintCapabilities 和 PrintTicket XML 資料流)。
將 Stream 傳遞至 DefinedFeatures 屬性所參考之 DefinedFeaturesPrintTicket 物件的建構函式。該建構函式只會忽略 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:namespace-abbreviation=full-namespace-name> (其中 full-namespace-name 是用來識別會定義新功能之結構描述的 URL,而 namespace-abbreviation 則是這個 URL 的縮寫)。
下列程式碼範例顯示當此程序套用至點字印表機範例時的部分輸出 (為求節省空間及簡化起見,此範例已省略了許多部分)。請注意,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 類別擁有的 PrivateNamespace 屬性將與您為 NewFeaturesPrintTicket 建立的屬性相同。
除了繼承自 Object 類別的方法以外,所有的類別都不會有其他任何方法。
每個類別都有一個採用 Stream 參數的單一建構函式。該 Stream 是 PrintCapabilities 文件。
在使用 Stream 來初始化屬性之前,DefinedFeaturesPrintCapabilities 建構函式必須先驗證傳遞給它的 Stream 是否符合Print Schema Framework(其中一種簡單的驗證方式是先將 Stream 傳遞到 PrintCapabilities 建構函式。如果後者沒有擲回例外狀況,即表示資料流是有效的)。
在使用 Stream 來初始化屬性之前,NewFeaturesPrintCapabilities 建構函式必須先驗證傳遞給它的 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 Paper Specification (XPS) 文件使用,則 System.Windows.Xps、System.Windows.Xps.Packaging 和 System.Windows.Xps.Serialization 命名空間中會有設計用來讀取及寫入 XPS 文件 (包括讀取及寫入 PrintTicket) 的 API。如需將 PrintTicket 的關聯性加入至封裝的詳細資訊,請參閱 PackageRelationship。
如需 PrintTicket 文件和 PrintCapabilities 文件的完整範例,請參閱 PrintTicket Example和 PrintCapabilities Document Example。
下面是 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>
請注意,上列範例列出了該功能每個可能的選項 (包括定序及非定序兩種),並識別各選項的狀態 (即其是否受條件約束)。完整的 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 文件寫作程式」(MXDW) 驅動程式。如需詳細資訊,請參閱 MXDW 組態設定。
如果我們假設虛構的 Ajax Embosser's 公司定義了 BrailleGrade3 轉譯功能,而其定義的方法與 Microsoft 定義文件定序功能的方法一致,我們就可以看到此功能的 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 命名空間執行的作業範例,請參閱 HOW TO:複製印表機和 HOW TO:取得列印系統物件屬性但不使用反映。
前述範例並不需要執行這項作業,因為我們加入 BrailleEmbosser 類別中的唯一屬性是 IsBraile3Enabled,而它又是 Boolean。這個範例中已經有 System.Printing.IndexedProperties.PrintBooleanProperty 類別了。
請參閱
工作
參考
System.Printing.IndexedProperties
System.Windows.Xps.Serialization