印刷の概要

Microsoft .NET Framework では、Windows Presentation Foundation (WPF) を使用するアプリケーション開発者は、豊富な新しい印刷および印刷システム管理 API を利用できます。 また、Windows Vista では、Windows フォーム アプリケーションを作成する開発者と、アンマネージド コードを使用する開発者も、これらの印刷システム拡張機能の一部を使用できます。 この新しい機能の中核となるのが、新しい XML Paper Specification (XPS) ファイル形式と XPS 印刷パスです。

このトピックは、次のセクションで構成されています。

XPS について

XPS は、電子ドキュメント形式、スプール ファイル形式、およびページ記述言語です。 XML、Open Packaging Conventions (OPC)、その他の業界標を使用してクロスプラットフォームのドキュメントを作成する OpenDocument 形式の 1 つです。 XPS により、デジタル ドキュメントの作成、共有、印刷、表示、アーカイブを行うプロセスが簡略化されます。 XPS の追加情報については、「XPS ドキュメント」を参照してください。

WPF を使用した XPS ベースのコンテンツの印刷手法のいくつかは、「XPS ファイルをプログラムにより印刷する」で説明されています。 このトピックに含まれるコンテンツの確認中にこれらのサンプルを参照すると、役に立つ場合があります。 (アンマネージド コードの開発者は、MXDC_ESCAPE 関数のドキュメントを参照することをお勧めします。Windows フォーム開発者は、System.Drawing.Printing 名前空間の API を使う必要があります。これは完全な XPS 印刷パスをサポートしませんが、ハイブリッド GDI-to-XPS 印刷パスをサポートしています。後述する「印刷パスのアーキテクチャ」を参照してください。)

XPS 印刷パス

XML Paper Specification (XPS) 印刷パスは、Windows アプリケーションでの印刷の処理方法を再定義する Windows の新機能です。 XPS は、ドキュメントのプレゼンテーション言語 (RTF など)、印刷スプーラの形式 (WMF など)、ページ記述言語 (PCL や Postscript など) に置き換えることができるため、新しい印刷パスでは、アプリケーションの公開から印刷ドライバーまたはデバイスでの最終処理まで、XPS 形式が維持されます。

XPS 印刷パスは、XPS のプリンター ドライバー モデル (XPSDrv) 上に構築されています。XPSDrv により、開発者は "What You See Is What You Get" (WYSIWYG) の印刷、色のサポートの向上、および印刷のパフォーマンスの大幅な向上など、いくつかの利点を得られます。 (XPSDrv の詳細については、Windows Driver Kit のドキュメントをご覧ください)。

XPS ドキュメントの印刷スプーラの操作は、基本的に Windows の以前のバージョンと同じです。 ただし、既存の GDI 印刷パスに加えて XPS 印刷パスをサポートするように強化されました。 新しい印刷パスで、XPS スプール ファイルがネイティブに使用されます。 Windows の以前のバージョン向けに記述されたユーザー モードのプリンター ドライバーは引き続き機能しますが、XPS 印刷パスを使用するためには、XPS プリンター ドライバー (XPSDrv) が必要になります。

XPS 印刷パスには次のような大きな利点があります。

  • WYSIWYG 印刷のサポート

  • 高度なカラー プロファイルのネイティブ サポート (1 チャンネルあたり 32 ビット (bpc)、CMYK、名前付きの色、n インクなど)、および透明度とグラデーションのネイティブ サポート。

  • .NET Framework と Win32 ベースのアプリケーションの両方における印刷パフォーマンスの向上。

  • 業界標準の XPS 形式。

基本的な印刷シナリオでは、ユーザー インターフェイス、構成、およびジョブの送信用の 1 つのエントリ ポイントで、簡単かつ直感的な API を使用できます。 高度なシナリオの場合、UI、同期または非同期の印刷、一括印刷の機能にサポートが追加されます。 いずれのオプションでも、完全または部分的な信頼モードでの印刷のサポートを提供します。

XPS は、拡張性を考慮して設計されています。 機能拡張フレームワークを使用して、機能を XPS にモジュール形式で追加できます。 拡張機能は、次のとおりです。

  • 印刷スキーマ。 パブリックのスキーマは定期的に更新され、デバイスの機能を迅速に拡張することができます。 (下記の「PrintTicket と PrintCapabilities」をご覧ください。)

  • 拡張可能なフィルター パイプライン。 XPS プリンター ドライバー (XPSDrv) フィルター パイプラインは、XPS ドキュメントの直接的および拡張性の高い印刷を可能にするように作られています。 詳細については、「XPSDrv プリンター ドライバー」を参照してください。

Win32 アプリケーションと .NET Framework アプリケーションでは XPS がサポートされていますが、Win32 アプリケーションと Windows フォーム アプリケーションでは、XPS プリンター ドライバー (XPSDrv) 用に XPS 形式のコンテンツを作成するため、GDI から XPS への変換が使用されます。 これらのアプリケーションでは、XPS 印刷パスを使用する必要はなく、Enhanced Metafile (EMF) ベースの印刷を引き続き使用できます。 ただし、XPS の機能と拡張機能のほとんどは、XPS 印刷パスを対象としたアプリケーション以外では使用できません。

Win32 アプリケーションと Windows フォーム アプリケーションで XPSDrv ベースのプリンターを使用できるようにするため、XPS プリンター ドライバー (XPSDrv) では GDI 形式から XPS 形式への変換がサポートされています。 XPSDrv モデルには XPS 形式から GDI 形式へのコンバーターも用意されているため、Win32 アプリケーションで XPS ドキュメントを印刷できます。 WPF アプリケーションでは、書き込み操作の対象の印刷キューに XPSDrv ドライバーがない場合は常に、XpsDocumentWriter クラスの Write メソッドと WriteAsync メソッドによって、XPS 形式から GDI 形式への変換が自動的に行われます。 (Windows フォーム アプリケーションでは XPS ドキュメントを印刷できません)。

次の図では、印刷サブシステムが示され、Microsoft によって提供される部分と、ソフトウェアおよびハードウェアのベンダーによって定義される部分が示されています。

Screenshot shows the XPS print system.

XPS の基本的な印刷

WPF では、基本 API と高度な API の両方が定義されています。 広範な印刷のカスタマイズや完全な XPS の機能セットへのアクセスを必要としないアプリケーションでは、基本的な印刷サポートを使用できます。 基本的な印刷サポートは、最小構成を必要とし、使い慣れた UI を特長とする印刷ダイアログ コントロールを介して公開されます。 XPS の機能の多くは、この簡略化された印刷モデルによって使用できます。

PrintDialog

System.Windows.Controls.PrintDialog コントロールには、UI、構成、および XPS ジョブの送信用に 1 つのエントリ ポイントが用意されています。 コントロールのインスタンス化と使用方法については、「方法 : 印刷ダイアログ ボックスを呼び出す」をご覧ください。

高度な XPS の印刷

XPS 機能の完全なセットにアクセスするには、高度な印刷 API を使用する必要があります。 いくつかの関連する API について、以下で詳しく説明します。 XPS 印刷パス API の完全な一覧については、System.Windows.Xps および System.Printing 名前空間のリファレンスを参照してください。

PrintTicket と PrintCapabilities

PrintTicket クラスと PrintCapabilities クラスは、XPS の高度な機能の基盤となります。 いずれの種類のオブジェクトも、照合順序、両面印刷、ホチキス止めなど、XML 形式の印刷向け機能の構造になっています。これらの構造は、印刷スキーマによって定義されます。 PrintTicket は、プリンターに印刷ジョブの処理方法を指示します。 PrintCapabilities クラスは、プリンターの機能を定義します。 プリンターの機能のクエリを実行すると、プリンターのサポート機能を最大限に活用する PrintTicket を作成できます。 同様に、サポートされていない機能を回避できます。

次の例は、プリンターの PrintCapabilities でクエリを実行する方法と、コードを使用した PrintTicket の作成方法を示しています。

// ---------------------- GetPrintTicketFromPrinter -----------------------
/// <summary>
///   Returns a PrintTicket based on the current default printer.</summary>
/// <returns>
///   A PrintTicket for the current local default printer.</returns>
PrintTicket^ GetPrintTicketFromPrinter () 
{
   PrintQueue^ printQueue = nullptr;

   LocalPrintServer^ localPrintServer = gcnew LocalPrintServer();

   // Retrieving collection of local printer on user machine
   PrintQueueCollection^ localPrinterCollection = localPrintServer->GetPrintQueues();

   System::Collections::IEnumerator^ localPrinterEnumerator = localPrinterCollection->GetEnumerator();

   if (localPrinterEnumerator->MoveNext())
   {
      // Get PrintQueue from first available printer
      printQueue = ((PrintQueue^)localPrinterEnumerator->Current);
   } else
   {
      return nullptr;
   }
   // Get default PrintTicket from printer
   PrintTicket^ printTicket = printQueue->DefaultPrintTicket;

   PrintCapabilities^ printCapabilites = printQueue->GetPrintCapabilities();

   // Modify PrintTicket
   if (printCapabilites->CollationCapability->Contains(Collation::Collated))
   {
      printTicket->Collation = Collation::Collated;
   }
   if (printCapabilites->DuplexingCapability->Contains(Duplexing::TwoSidedLongEdge))
   {
      printTicket->Duplexing = Duplexing::TwoSidedLongEdge;
   }
   if (printCapabilites->StaplingCapability->Contains(Stapling::StapleDualLeft))
   {
      printTicket->Stapling = Stapling::StapleDualLeft;
   }
   return printTicket;
};// end:GetPrintTicketFromPrinter()
// ---------------------- GetPrintTicketFromPrinter -----------------------
/// <summary>
///   Returns a PrintTicket based on the current default printer.</summary>
/// <returns>
///   A PrintTicket for the current local default printer.</returns>
private PrintTicket GetPrintTicketFromPrinter()
{
    PrintQueue printQueue = null;

    LocalPrintServer localPrintServer = new LocalPrintServer();

    // Retrieving collection of local printer on user machine
    PrintQueueCollection localPrinterCollection =
        localPrintServer.GetPrintQueues();

    System.Collections.IEnumerator localPrinterEnumerator =
        localPrinterCollection.GetEnumerator();

    if (localPrinterEnumerator.MoveNext())
    {
        // Get PrintQueue from first available printer
        printQueue = (PrintQueue)localPrinterEnumerator.Current;
    }
    else
    {
        // No printer exist, return null PrintTicket
        return null;
    }

    // Get default PrintTicket from printer
    PrintTicket printTicket = printQueue.DefaultPrintTicket;

    PrintCapabilities printCapabilites = printQueue.GetPrintCapabilities();

    // Modify PrintTicket
    if (printCapabilites.CollationCapability.Contains(Collation.Collated))
    {
        printTicket.Collation = Collation.Collated;
    }

    if ( printCapabilites.DuplexingCapability.Contains(
            Duplexing.TwoSidedLongEdge) )
    {
        printTicket.Duplexing = Duplexing.TwoSidedLongEdge;
    }

    if (printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft))
    {
        printTicket.Stapling = Stapling.StapleDualLeft;
    }

    return printTicket;
}// end:GetPrintTicketFromPrinter()
' ---------------------- GetPrintTicketFromPrinter -----------------------
''' <summary>
'''   Returns a PrintTicket based on the current default printer.</summary>
''' <returns>
'''   A PrintTicket for the current local default printer.</returns>
Private Function GetPrintTicketFromPrinter() As PrintTicket
    Dim printQueue As PrintQueue = Nothing

    Dim localPrintServer As New LocalPrintServer()

    ' Retrieving collection of local printer on user machine
    Dim localPrinterCollection As PrintQueueCollection = localPrintServer.GetPrintQueues()

    Dim localPrinterEnumerator As System.Collections.IEnumerator = localPrinterCollection.GetEnumerator()

    If localPrinterEnumerator.MoveNext() Then
        ' Get PrintQueue from first available printer
        printQueue = CType(localPrinterEnumerator.Current, PrintQueue)
    Else
        ' No printer exist, return null PrintTicket
        Return Nothing
    End If

    ' Get default PrintTicket from printer
    Dim printTicket As PrintTicket = printQueue.DefaultPrintTicket

    Dim printCapabilites As PrintCapabilities = printQueue.GetPrintCapabilities()

    ' Modify PrintTicket
    If printCapabilites.CollationCapability.Contains(Collation.Collated) Then
        printTicket.Collation = Collation.Collated
    End If

    If printCapabilites.DuplexingCapability.Contains(Duplexing.TwoSidedLongEdge) Then
        printTicket.Duplexing = Duplexing.TwoSidedLongEdge
    End If

    If printCapabilites.StaplingCapability.Contains(Stapling.StapleDualLeft) Then
        printTicket.Stapling = Stapling.StapleDualLeft
    End If

    Return printTicket
End Function ' end:GetPrintTicketFromPrinter()

PrintServer と PrintQueue

PrintServer クラスはネットワーク プリント サーバーを表し、PrintQueue クラスはプリンターとそれに関連付けられた出力ジョブのキューを表します。 これらの API を併用すると、サーバーの印刷ジョブを高度に管理できます。 PrintServer、またはその派生クラスのいずれかを使用すると、PrintQueue を管理できます。 新しい印刷ジョブをキューに挿入するには、AddJob メソッドを使用します。

次の例は、コードを使用して LocalPrintServer を作成し、既定の PrintQueue にアクセスする方法を示しています。

// -------------------- GetPrintXpsDocumentWriter() -------------------
/// <summary>
///   Returns an XpsDocumentWriter for the default print queue.</summary>
/// <returns>
///   An XpsDocumentWriter for the default print queue.</returns>
private XpsDocumentWriter GetPrintXpsDocumentWriter()
{
    // Create a local print server
    LocalPrintServer ps = new LocalPrintServer();

    // Get the default print queue
    PrintQueue pq = ps.DefaultPrintQueue;

    // Get an XpsDocumentWriter for the default print queue
    XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(pq);
    return xpsdw;
}// end:GetPrintXpsDocumentWriter()
' -------------------- GetPrintXpsDocumentWriter() -------------------
''' <summary>
'''   Returns an XpsDocumentWriter for the default print queue.</summary>
''' <returns>
'''   An XpsDocumentWriter for the default print queue.</returns>
Private Function GetPrintXpsDocumentWriter() As XpsDocumentWriter
    ' Create a local print server
    Dim ps As New LocalPrintServer()

    ' Get the default print queue
    Dim pq As PrintQueue = ps.DefaultPrintQueue

    ' Get an XpsDocumentWriter for the default print queue
    Dim xpsdw As XpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(pq)
    Return xpsdw
End Function ' end:GetPrintXpsDocumentWriter()

XpsDocumentWriter

XpsDocumentWriter を、その多くの Write メソッドおよび WriteAsync メソッドと共に使用すると、XPS ドキュメントを PrintQueue に書き込むことができます。 たとえば、Write(FixedPage, PrintTicket) メソッドを使用すると、XPS ドキュメントと PrintTicket を同期的に出力できます。 WriteAsync(FixedDocument, PrintTicket) メソッドを使用すると、XPS ドキュメントと PrintTicket を非同期的に出力できます。

次の例は、コードを使用して XpsDocumentWriter を作成する方法を示しています。

// -------------------- GetPrintXpsDocumentWriter() -------------------
/// <summary>
///   Returns an XpsDocumentWriter for the default print queue.</summary>
/// <returns>
///   An XpsDocumentWriter for the default print queue.</returns>
private XpsDocumentWriter GetPrintXpsDocumentWriter()
{
    // Create a local print server
    LocalPrintServer ps = new LocalPrintServer();

    // Get the default print queue
    PrintQueue pq = ps.DefaultPrintQueue;

    // Get an XpsDocumentWriter for the default print queue
    XpsDocumentWriter xpsdw = PrintQueue.CreateXpsDocumentWriter(pq);
    return xpsdw;
}// end:GetPrintXpsDocumentWriter()
' -------------------- GetPrintXpsDocumentWriter() -------------------
''' <summary>
'''   Returns an XpsDocumentWriter for the default print queue.</summary>
''' <returns>
'''   An XpsDocumentWriter for the default print queue.</returns>
Private Function GetPrintXpsDocumentWriter() As XpsDocumentWriter
    ' Create a local print server
    Dim ps As New LocalPrintServer()

    ' Get the default print queue
    Dim pq As PrintQueue = ps.DefaultPrintQueue

    ' Get an XpsDocumentWriter for the default print queue
    Dim xpsdw As XpsDocumentWriter = PrintQueue.CreateXpsDocumentWriter(pq)
    Return xpsdw
End Function ' end:GetPrintXpsDocumentWriter()

さらに AddJob メソッドは印刷方法を提供します。 「方法 : XPS ファイルをプログラムにより印刷する」をご覧ください。 詳細について。

GDI 印刷パス

WPF アプリケーションでは XPS 印刷パスがネイティブにサポートされていますが、Win32 アプリケーションと Windows フォーム アプリケーションでも一部の XPS の機能を利用できます。 XPS プリンター ドライバー (XPSDrv) では、GDI ベースの出力を XPS 形式に変換できます。 高度なシナリオ用に、Microsoft XPS Document Converter (MXDC) を使用した、コンテンツのカスタム変換がサポートされています。 同様に、WPF アプリケーションでも、XpsDocumentWriter クラスの Write メソッドまたは WriteAsync メソッドのいずれかを呼び出し、対象の印刷キューとして XpsDrv 以外のプリンターを指定することにより、GDI 印刷パスに出力することができます。

XPS の機能またはサポートを必要としないアプリケーションでは、現在の GDI 印刷パスは変更されません。

XPSDrv ドライバー モデル

XPS 印刷パスでは、XPS 対応のプリンターまたはドライバーに出力する場合に、ネイティブの印刷スプール形式として XPS を使用すると、スプーラーの効率性が高まります。 スプール処理の簡略化により、ドキュメントをスプールする前に、EMF データ ファイルなどの中間スプール ファイルを生成する必要がなくなります。 スプール ファイルのサイズを小さくすると、XPS 印刷パスのネットワーク トラフィックが減少し、印刷のパフォーマンスが向上します。

EMF は、サービスのレンダリングのために、アプリケーションの出力を GDI に対する一連の呼び出しとして表すクローズ形式です。 EMF と異なり、XPS スプール形式では、XPS ベースのプリンター ドライバー (XPSDrv) に出力するときにさらに解釈する必要のない、実際のドキュメントが表されます。 ドライバーは、その形式のデータを直接操作できます。 この機能により、EMF ファイルと GDI ベースの印刷ドライバーを使用するときに、データと色空間の変換が必要なくなります。

同等の EMF と比較すると、XPS プリンター ドライバー (XPSDrv) を対象とする XPS ドキュメントを使用すると、通常はスプール ファイルのサイズが減少します。ただし、例外もあります。

  • ベクター グラフィックが非常に複雑で、複数の階層があるか、非効率的に記述されている場合、同じグラフィックスのビットマップ形式のバージョンよりもサイズが大きくなることがあります。

  • 画面表示の目的で、XPS ファイルにはデバイス フォントおよびコンピューター ベースのフォントが埋め込まれます。一方、GDI のスプール ファイルにはデバイス フォントは埋め込まれません。 しかし、両方の種類のフォントがサブセット化されているため (下記参照)、プリンター ドライバーは、ファイルをプリンターに送信する前にデバイス フォントを削除することができます。

スプール サイズの削減は、いくつかのメカニズムを通じて行われます。

  • フォントのサブセット化。 実際のドキュメント内で使用される文字のみが XPS ファイルに格納されます。

  • 高度なグラフィックスのサポート。 透過性とグラデーションのプリミティブのネイティブ サポートにより、XPS ドキュメントの内容のラスタライズを回避できます。

  • 共通リソースの識別。 複数回使用するリソース (会社のロゴを表す画像など) は共有リソースとして扱われ、一度だけ読み込まれます。

  • ZIP 圧縮。 すべての XPS ドキュメントで ZIP 圧縮が使用されます。

関連項目