다음을 통해 공유


인쇄 개요

Microsoft .NET Framework를 통해 WPF(Windows Presentation Foundation)를 사용하는 애플리케이션 개발자는 새롭고 다양한 인쇄 및 인쇄 시스템 관리 API 세트를 갖게 됩니다. Windows Vista에서는 Windows Forms 애플리케이션을 만드는 개발자와 비관리 코드를 사용하는 개발자도 이러한 인쇄 시스템 향상 기능을 일부 사용할 수 있습니다. 이 새로운 기능의 핵심은 새 XPS(XML Paper Specification) 파일 형식과 XPS 인쇄 경로입니다.

이 항목에는 다음과 같은 섹션이 포함되어 있습니다.

XPS 정보

XPS는 전자 문서 형식, 스풀 파일 형식 및 페이지 설명 언어입니다. XML, OPC(Open Packaging Conventions) 및 기타 산업 표준을 사용하여 플랫폼 간 문서를 만드는 개방형 문서 형식입니다. XPS는 디지털 문서를 만들고, 공유하고, 인쇄하고, 보고, 보관하는 프로세스를 간소화합니다. XPS에 대한 자세한 내용은 XPS 문서를 참조하세요.

WPF를 사용하여 XPS 기반 콘텐츠를 인쇄하는 여러 가지 기술은 프로그래밍 방식으로 XPS 파일 인쇄에서 보여 줍니다. 이 항목에 포함된 내용을 검토하는 동안 이러한 예제를 참조하는 것이 유용할 수도 있습니다. (비관리 코드 개발자는 MXDC_ESCAPE 함수에 대한 설명서를 참조해야 합니다. Windows Forms 개발자는 전체 XPS 인쇄 경로를 지원하지 않지만 하이브리드 GDI-XPS 인쇄 경로를 지원하는 System.Drawing.Printing 네임스페이스의 API를 사용해야 합니다. 아래의 인쇄 경로 아키텍처를 참조하세요.)

XPS 인쇄 경로

XPS(XML Paper Specification) 인쇄 경로는 Windows 애플리케이션에서 인쇄를 처리하는 방법을 다시 정의하는 새로운 Windows 기능입니다. XPS는 문서 표시 언어(예: RTF), 인쇄 스풀러 형식(예: WMF) 및 페이지 설명 언어(예: PCL 또는 포스트스크립트)를 대체할 수 있습니다. 새로운 인쇄 경로는 인쇄 드라이버 또는 디바이스에서 애플리케이션 게시부터 최종 처리까지 XPS 형식을 유지 관리합니다.

XPS 인쇄 경로는 XPS 프린터 드라이버 모델(XPSDrv)을 기반으로 하며 "WYSIWYG(보이는 대로 편집)" 인쇄, 향상된 색 지원, 크게 향상된 인쇄 성능 등 개발자에게 여러 가지 이점을 제공합니다. (XPSDrv에 대한 자세한 내용은 Windows 드라이버 키트 개발을 참조하세요.)

XPS 문서에 대한 인쇄 스풀러 작업은 기본적으로 이전 버전의 Windows와 동일합니다. 그러나 기존의 GDI 인쇄 경로뿐 아니라 XPS 인쇄 경로도 지원하도록 향상되었습니다. 새로운 인쇄 경로는 기본적으로 XPS 스풀 파일을 사용합니다. 이전 버전의 Windows용으로 작성된 사용자 모드 프린터 드라이버도 계속 작동하지만 XPS 인쇄 경로를 사용하려면 XPS 프린터 드라이버(XPSDrv)가 필요합니다.

XPS 인쇄 경로에는 다음과 같은 중요한 장점이 있습니다.

  • WYSIWYG 인쇄 지원

  • 32bpc(채널당 비트), CMYK, 명명된 색, n-잉크 및 투명도와 그라데이션 기본 지원을 포함하는 고급 색 프로필에 대한 기본 지원입니다.

  • .NET Framework 및 Win32 기반 애플리케이션 둘 다에 대한 인쇄 성능이 향상되었습니다.

  • 업계 표준 XPS 형식입니다.

기본 인쇄 시나리오에서는 사용자 인터페이스, 구성 및 작업 제출을 위한 단일 진입점으로 간단하고 직관적인 API를 사용할 수 있습니다. 고급 시나리오에서는 UI, 동기 또는 비동기 인쇄 및 일괄 처리 인쇄 기능을 위한 추가 지원이 추가됩니다. 두 옵션 모두 완전 신뢰 또는 부분 신뢰 모드로 인쇄 지원을 제공합니다.

XPS는 확장성을 염두에 두고 설계되었습니다. 확장성 프레임워크를 사용하여 모듈형 방식으로 XPS에 기능 및 특성을 추가할 수 있습니다. 확장성 기능은 다음과 같습니다.

  • 인쇄 스키마. 공용 스키마는 정기적으로 업데이트되며 디바이스 기능을 빠르게 확장할 수 있게 해줍니다. 아래의 PrintTicket 및 PrintCapabilities를 참조하세요.

  • 확장 가능한 필터 파이프라인. XPS 프린터 드라이버(XPSDrv) 필터 파이프라인은 XPS 문서의 직접 인쇄와 확장 가능한 인쇄를 둘 다 사용할 수 있도록 설계되었습니다. 자세한 내용은 XPSDrv 프린터 드라이버를 참조하세요.

Win32 및 .NET Framework 애플리케이션은 모두 XPS를 지원하지만 Win32 및 Windows Forms 애플리케이션은 XPS 프린터 드라이버(XPSDrv)에 대한 XPS 형식의 콘텐츠를 만들기 위해 GDI에서 XPS로 변환을 사용합니다. 이러한 애플리케이션은 XPS 인쇄 경로를 사용할 필요가 없으며 EMF(Enhanced Metafile) 기반 인쇄를 계속 사용할 수 있습니다. 그러나 대부분의 XPS 기능과 향상된 기능은 XPS 인쇄 경로를 대상으로 하는 애플리케이션만 사용할 수 있습니다.

Win32 및 Windows Forms 애플리케이션에서 XPSDrv 기반 프린터를 사용할 수 있도록 XPS 프린터 드라이버(XPSDrv)는 GDI를 XPS 형식으로 변환하는 것을 지원합니다. XPSDrv 모델은 Win32 애플리케이션에서 XPS 문서를 인쇄할 수 있도록 XPS를 GDI 형식으로 변환하는 변환기도 제공합니다. WPF 애플리케이션의 경우 쓰기 작업의 대상 인쇄 큐에 XPSDrv 드라이버가 없을 때마다 XpsDocumentWriter 클래스의 WriteWriteAsync 메서드에 의해 XPS에서 GDI 형식으로 변환이 자동으로 수행됩니다. (Windows Forms 애플리케이션에서 XPS 문서를 인쇄할 수 없습니다.)

다음 그림에서는 인쇄 하위 시스템을 보여 주며 Microsoft에서 제공하는 부분과 소프트웨어 및 하드웨어 공급업체에서 정의되는 부분을 정의합니다.

XPS 인쇄 시스템을 보여주는 스크린샷.

기본 XPS 인쇄

WPF는 기본 및 고급 API를 둘 다 정의합니다. 광범위한 인쇄 사용자 지정이나 전체 XPS 기능 집합에 대한 액세스가 필요하지 않은 애플리케이션의 경우 기본 인쇄 지원을 사용할 수 있습니다. 기본 인쇄 지원은 최소한의 구성이 필요하며 익숙한 UI를 제공하는 인쇄 대화 상자 컨트롤을 통해 노출됩니다. 이 간소화된 인쇄 모델을 통해 많은 XPS 기능을 사용할 수 있습니다.

PrintDialog

System.Windows.Controls.PrintDialog 컨트롤은 UI, 구성 및 XPS 작업 제출을 위한 단일 진입점을 제공합니다. 컨트롤을 인스턴스화하고 사용하는 방법에 대한 자세한 내용은 인쇄 대화 상자 호출을 참조하세요.

고급 XPS 인쇄

XPS 기능의 전체 세트에 액세스하려면 고급 인쇄 API를 사용해야 합니다. 아래에서는 여러 관련 API에 대해 자세히 설명합니다. XPS 인쇄 경로 API의 전체 목록은 System.Windows.XpsSystem.Printing 네임스페이스 참조를 참조하세요.

PrintTicket 및 PrintCapabilities

PrintTicketPrintCapabilities 클래스는 고급 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

많은 WriteWriteAsync 메서드와 더불어 XpsDocumentWriter는 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 Forms 애플리케이션도 일부 XPS 기능을 이용할 수 있습니다. XPS 프린터 드라이버(XPSDrv)는 GDI 기반 출력을 XPS 형식으로 변환할 수 있습니다. 고급 시나리오에서는 MXDC(Microsoft XPS 문서 변환기)를 통해 콘텐츠의 사용자 지정 변환이 지원됩니다. 마찬가지로 WPF 애플리케이션은 XpsDocumentWriter 클래스의 Write 또는 WriteAsync 메서드 중 하나를 호출하고 XpsDrv가 아닌 프린터를 대상 인쇄 큐로 지정하여 GDI 인쇄 경로로 출력할 수도 있습니다.

XPS 기능이나 지원이 필요하지 않은 애플리케이션의 경우 현재 GDI 인쇄 경로가 변경되지 않은 상태로 유지됩니다.

XPSDrv 드라이버 모델

XPS 인쇄 경로는 XPS 사용 프린터 또는 드라이버에 인쇄할 때 XPS를 기본 인쇄 스풀 형식으로 사용하여 스풀러 효율성을 향상시킵니다. 간소화된 스풀링 프로세스에서는 문서가 스풀링되기 전에 EMF 데이터 파일과 같은 중간 스풀 파일을 생성할 필요가 없습니다. 작은 스풀 파일 크기를 통해 XPS 인쇄 경로는 네트워크 트래픽을 줄이고 인쇄 성능을 향상시킬 수 있습니다.

EMF는 애플리케이션 출력을 렌더링 서비스에 대한 일련의 GDI 호출로 나타내는 닫힌 형식입니다. EMF와 달리 XPS 스풀 형식은 XPS 기반 프린터 드라이버(XPSDrv)에 출력할 때 추가 해석을 요구하지 않고 실제 문서를 나타냅니다. 드라이버가 형식의 데이터에 대해 직접 작동할 수 있습니다. 이 기능은 EMF 파일과 GDI 기반 인쇄 드라이버를 사용할 때 필요한 데이터 및 색 공간 변환을 제거합니다.

일반적으로 XPS 프린터 드라이버(XPSDrv)를 대상으로 하는 XPS 문서를 사용하는 경우 해당 EMF에 비해 스풀 파일 크기가 감소하지만 다음과 같은 예외도 있습니다.

  • 매우 복잡하거나 다중 계층이거나 비효율적으로 작성된 벡터 그래픽은 동일한 그래픽의 비트맵 버전보다 클 수 있습니다.

  • 화면 표시를 위해 XPS 파일은 디바이스 글꼴과 컴퓨터 기반 글꼴을 포함하는 반면 GDI 스풀 파일은 디바이스 글꼴을 포함하지 않습니다. 그러나 두 종류의 글꼴은 모두 하위 집합으로 지정되며(아래 참조), 프린터 드라이버가 파일을 프린터로 전송하기 전에 디바이스 글꼴을 제거할 수 있습니다.

스풀 크기 감소는 다음과 같은 여러 메커니즘을 통해 수행됩니다.

  • 글꼴 하위 집합. 실제 문서 내에서 사용되는 문자만 XPS 파일에 저장됩니다.

  • 고급 그래픽 지원. 투명도 및 그라데이션 기본 형식에 대한 기본 지원을 통해 XPS 문서에서 콘텐츠의 래스터화를 방지합니다.

  • 공용 리소스 식별. 여러 번 사용되는 리소스(예: 회사 로고를 나타내는 이미지)는 공유 리소스로 처리되며 한 번만 로드됩니다.

  • ZIP 압축. 모든 XPS 문서가 ZIP 압축을 사용합니다.

참고 항목