다음을 통해 공유


XPS OM 인쇄

XPS OM을 프린터에 XPS 문서로 보내는 방법을 설명합니다.

전체 XPS 문서를 포함하는 XPS OM을 인쇄하는 방법에 대한 지침은 전체 XPS OM 인쇄를 참조하세요. XPS 문서를 포함하려면 XPS OM에 빈 XPS OM 만들기에 나열된 항목이 포함되어야 합니다.

한 번에 한 페이지를 만들거나 처리하는 XPS OM을 인쇄하는 방법에 대한 지침은 XPS OM을 증분 인쇄를 참조하세요.

프로그램에서 이러한 코드 예제를 사용하기 전에 공통 XPS 문서 프로그래밍 작업의 고지 사항을 읽어 보세요.

이 항목에서는 다음 작업을 수행하는 방법을 알아봅니다.

XPS OM에 전체 XPS 문서가 포함된 경우 IXpsOMPackage 인터페이스의 WriteToStream 메서드는 XPS OM의 내용을 프린터 또는 인쇄 큐로 보낼 수 있습니다.

인쇄 작업이 완료된 시기를 감지하려면 다음 예제와 같이 이벤트 핸들을 만듭니다.

    HANDLE completionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (NULL == completionEvent)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        // The method can continue, but print spooling completion
        //  cannot be checked without a valid event handle.
    }

전체 XPS OM을 인쇄하려면 다음을 수행합니다.

  1. StartXpsPrintJob을 호출하여 새 인쇄 작업 스트림을 만듭니다.
  2. 패키지의 WriteToStream 메서드를 호출하여 XPS OM의 콘텐츠를 스트림에 보냅니다.
  3. 스트림의 Close 메서드를 호출하여 인쇄 작업 스트림 을 닫습니다 .
  4. 인쇄 작업이 완료되었음을 알릴 때까지 기다립니다.
  5. 완료 상태 확인합니다.
  6. 리소스를 닫고 해제합니다.
    IXpsPrintJob *job = NULL;
    IXpsPrintJobStream *jobStream = NULL;
    hr = StartXpsPrintJob(
                printerName,
                NULL,
                NULL,
                NULL,
                completionEvent,
                NULL,
                0,
                &job,
                &jobStream,
                NULL);

    // Write package to print job stream
    hr = package->WriteToStream (jobStream, FALSE);

    // Close the stream to tell the print job
    // that the entire document has been sent.
    hr = jobStream->Close();

    // Wait for the print job to finish spooling...
    if (NULL != completionEvent) {
        if (WaitForSingleObject(completionEvent, INFINITE) == WAIT_OBJECT_0)
        {
            // Get the print job status to see why the wait completed.
            //  Note that without waiting for a completion event, 
            //  the print job may not be complete when the status is queried.
            XPS_JOB_STATUS jobStatus;
            hr = job->GetJobStatus(&jobStatus);

            // Evaluate the job status returned.
            switch (jobStatus.completion)
            {
                case XPS_JOB_COMPLETED:
                    // The job completed as expected.
                    hr = S_OK;
                    break;
                case XPS_JOB_CANCELLED:
                    // The job was canceled.
                    hr = E_FAIL;
                    break;
                case XPS_JOB_FAILED:
                    // The job failed, 
                    // jobStatus.jobStatus has the reason.
                    hr = E_FAIL;
                    break;
                default:
                    // An unexpected value was returned.
                    hr = E_UNEXPECTED;
                    break;
            }
                
            // Release completion event handle
            CloseHandle(completionEvent);
        }
        else
        {    // there was a problem, set hr to error status
            hr  = HRESULT_FROM_WIN32(GetLastError());
        }
    }

    // hr contains the result of the print operation

    CoUninitialize(); // if COM is no longer needed in this thread

XPS OM 증분 인쇄

XPS 인쇄 작업 스트림을 만든 다음 개별 문서 구성 요소를 인쇄 작업 스트림에 한 번에 하나씩 전달하여 XPS OM의 문서 구성 요소를 프린터 작업에 증분 방식으로 보낼 수 있습니다. 문서 구성 요소가 전송되는 순서에 따라 완성된 문서에 표시되는 방법이 결정됩니다. 따라서 프로그램에서 이 예제의 코드를 호출하려면 먼저 문서 구성 요소를 올바르게 구성해야 합니다.

XPS OM 인터페이스를 사용하기 전에 다음 예제 코드와 같이 스레드에서 COM을 초기화합니다.

    HRESULT hr;
    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);

인쇄 작업 완료를 모니터링하려면 다음 예제 코드와 같이 이벤트 핸들을 만듭니다.

    HANDLE completionEvent = NULL;
    completionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (NULL == completionEvent)
    {
        hr = HRESULT_FROM_WIN32(GetLastError());
        // The method can continue, but print spooling completion
        //  cannot be checked without a valid event handle.
    }

새 인쇄 작업 스트림 및 새 패키지 작성기를 만듭니다. 완성된 문서에 표시되는 것과 동일한 순서로 각 문서 구성 요소를 해당 패키지 작성기 메서드에 전달합니다.

각 문서를 새로 시작한 다음 페이지에 페이지를 추가합니다. 모든 문서 구성 요소를 인쇄 작업 스트림에 전달한 후 스트림을 닫고 인쇄 작업이 완료될 때까지 기다린 다음 열려 있는 리소스를 닫고 놓습니다.

  1. StartXpsPrintJob을 호출하여 새 인쇄 작업 스트림을 만듭니다.
  2. FixedDocumentSequence 부분에 대한 파트 URI를 만듭니다.
  3. 인쇄 작업 스트림에 새 패키지 작성기를 만듭니다.
  4. 각 문서를 작성하려면 다음을 수행합니다.
    1. FixedDocument 부분에 대한 새 파트 URI를 만듭니다.
    2. 패키지 작성기에서 새 문서를 시작합니다.
    3. 현재 문서의 각 페이지에 대해 FixedPage 파트에 대한 파트 URI를 만들고 패키지 작성기에 페이지를 추가합니다.
  5. 모든 페이지가 패키지 작성기에 추가된 후 닫습니다.
  6. 인쇄 작업 스트림을 닫습니다.
  7. 인쇄 작업이 완료되기를 기다립니다.
  8. 완료 상태 확인합니다.
  9. 열려 있는 리소스를 닫고 해제합니다.
    IXpsPrintJob* job = NULL;
    IXpsPrintJobStream* jobStream = NULL;
    hr = StartXpsPrintJob(
                argv[1],
                NULL,
                NULL,
                NULL,
                completionEvent,
                NULL,
                0,
                &job,
                &jobStream,
                NULL);

    // Note the implicit requirement that CoInitializeEx 
    //  has previously been called from this thread.
    IXpsOMObjectFactory *xpsFactory = NULL;
    hr = CoCreateInstance(
                __uuidof(XpsOMObjectFactory),
                NULL,
                CLSCTX_INPROC_SERVER,
                __uuidof(IXpsOMObjectFactory),
                reinterpret_cast<void**>(&xpsFactory)
                );
    // Create part URI for FixedDocumentSequence part
    //  This can use a static string because there is only one
    //  FixedDocumentSequence part in the print job.
    IOpcPartUri *partUri = NULL;
    hr = xpsFactory->CreatePartUri(L"/FixedDocumentSequence.fdseq", &partUri);

    // Create the package writer on the print job stream
    //  Note that the interleaving parameter set to 
    //  XPS_INTERLEAVING_ON, the package writer will create
    //  empty print ticket parts when a NULL pointer is
    //  passed in the print ticket argument of this method,
    //  the StartNewDocument method, and the AddPage method.
    //  For more information, see the help for these methods.
    IXpsOMPackageWriter *packageWriter = NULL;
    hr = xpsFactory->CreatePackageWriterOnStream(
            jobStream,
            TRUE,
            XPS_INTERLEAVING_ON, // to create blank print ticket objects
            partUri,
            NULL,
            NULL,
            NULL,
            NULL,
            &packageWriter);
    // release partUri after it's been used to create new doc. seq.
    if (partUri)
    {
        partUri->Release();
        partUri = NULL;
    }

    // Add document content to the print job stream.
    int docNumber = 1;
    int docsInPackage = 1; // Change this value as required.
    while (docNumber <= docsInPackage) {

        // Create a unique part URI for the current document.
        WCHAR DocPartUri[MAX_PATH];
        hr = MakeDocumentPartUri (docNumber, MAX_PATH, DocPartUri);
        hr = xpsFactory->CreatePartUri(DocPartUri, &partUri);
        
        // Initialize the new document in the package writer.
        hr = packageWriter->StartNewDocument(partUri, NULL, NULL, NULL, NULL);

        // release part URI after it's been used to create new doc.
        if (partUri)
        {
            partUri->Release();
            partUri = NULL;
        }

        // Add the pages
        int pageNumber = 1;
        int pagesInDocument = 1; // Change this value as required.
        while (pageNumber <= pagesInDocument) {

            // Create a unique part URI for the current page
            WCHAR PagePartUri[MAX_PATH];
            hr = MakePagePartUri (
                docNumber, 
                pageNumber, 
                MAX_PATH, 
                PagePartUri);
            hr = xpsFactory->CreatePartUri(PagePartUri, &partUri);

            // create page in OM
            XPS_SIZE pageSize = {816, 1056};
            IXpsOMPage *xpsPage = NULL;
            hr = xpsFactory->CreatePage(
                &pageSize, 
                L"en-US", 
                partUri, 
                &xpsPage);

            // release pagePartUri after it's been used to create the page
            if (partUri)
            {
                partUri->Release();
                partUri = NULL;
            }

            // add content to the page or retrieve 
            //  the page from the XPS OM.
            //  (not shown in this example)

            // add page to document
            hr = packageWriter->AddPage(
                        xpsPage,
                        &pageSize,
                        NULL,
                        NULL,
                        NULL,
                        NULL);

             if (xpsPage)
              {
                 xpsPage->Release();
                 xpsPage = NULL;
             }

            // go to the next page
            pageNumber++;
        }
        // the fixed document does not need to be closed.
        // it will be closed when a new fixed doc is opened
        // or the package is closed.

        // go to the next document
        docNumber++;
    }

    // Close the package writer when finished
    hr = packageWriter->Close();

    if (SUCCEEDED(hr))
    {
        // Close the print stream to tell the print
        //  job that the all document contents have
        //  been sent
        hr = jobStream->Close();
        // Wait for the print job to finish spooling...
        if (NULL != completionEvent) {
            if (WaitForSingleObject(completionEvent, INFINITE) == WAIT_OBJECT_0)
            {
                // Get the print job status to see why the wait completed.
                //  Note that without waiting for a completion event, 
                //  the print job may not be complete when the status is queried.
                XPS_JOB_STATUS jobStatus;
                hr = job->GetJobStatus(&jobStatus);

                // Evaluate the job status returned.
                switch (jobStatus.completion)
                {
                    case XPS_JOB_COMPLETED:
                        // The job completed as expected.
                        hr = S_OK;
                        break;
                    case XPS_JOB_CANCELLED:
                        // The job was canceled.
                        hr = E_FAIL;
                        break;
                    case XPS_JOB_FAILED:
                        // The job failed, 
                        // jobStatus.jobStatus has the reason.
                        hr = E_FAIL;
                        break;
                    default:
                        // An unexpected value was returned.
                        hr = E_UNEXPECTED;
                        break;
                }
                    
                // Release completion event handle
                CloseHandle(completionEvent);
            }
            else
            {    // there was a problem, set hr to error status
                hr  = HRESULT_FROM_WIN32(GetLastError());
            }
        }
    } 
    else
    {
        // cancel the job, if one exists, because
        //  the close call returned an error
        if (job) job->Cancel();
    }
    // hr contains the result of the print operation

    // free/release pointers and handles used.

    if (packageWriter)
    {
        packageWriter->Release();
        packageWriter = NULL;
    }

    if (partUri)
    {
        partUri->Release();
        partUri = NULL;
    }

    if (xpsFactory)
    {
        xpsFactory->Release();
        xpsFactory = NULL;
    }

    if (jobStream)
    {
        jobStream->Release();
        jobStream = NULL;
    }

    if (job)
    {
        job->Release();
        job = NULL;
    }

    if (completionEvent)
    {
        CloseHandle(completionEvent);
        completionEvent = NULL;
    }

    CoUninitialize(); // If done with COM in this thread.

이 예제와 같이 프로그램에서 문서 구성 요소를 증분 방식으로 작성하는 경우 인쇄 작업 스트림에 보내는 각 문서 파트의 파트 이름을 생성해야 합니다. 앞의 예제에서 FixedDocumentSequence 부분 URI는 XPS 문서에 하나만 해당 부분이 있기 때문에 정적 문자열에서 만들어집니다. 각 FixedPage 및 FixedDocument 부분의 URI는 XPS 문서 내에서 고유해야 합니다. 이러한 구성 요소의 인덱스를 사용하여 파트 URI를 빌드하면 결과 URI 문자열이 XPS 문서 내에서 고유하도록 할 수 있습니다.

HRESULT MakeDocumentPartUri (
                              __in int docNumber,
                              __in DWORD partUriStringLength,
                              __inout LPWSTR partUriStringBuffer
                              )
{
    // create a Part URI string using the document number
    //  that was passed as an argument
    // for example, "/Documents/1/FixedDocument.fdoc"
    //  where "1" specifies the document number, which would
    //  change with each document printed
    return S_OK;
}
 
HRESULT MakePagePartUri (
                              __in int docNumber,
                              __in int pageNumber,
                              __in DWORD partUriStringLength,
                              __inout LPWSTR partUriStringBuffer
                              )
{
    // create a Part URI string using the document number
    //   and page number that were passed as an argument
    // for example: "/Documents/1/Pages/1.fpage"
    //  where the first "1" between Documents and Pages 
    //  specifies the document number, which would change with
    //  each document. The second "1" specifies the page number,
    //  which would change with each page in the document.
    return S_OK;
}

XPS 문서의 구조에 대한 자세한 내용은 XML 용지 사양을 참조하세요.

다음 단계 

XPS 문서에 XPS OM 쓰기

이 섹션에서 사용됨

CoInitializeEx

CreateEvent

IOpcPartUri

IXpsOMPackage

IXpsOMPackageWriter

IXpsPrintJob

IXpsPrintJobStream

StartXpsPrintJob

단일 개체 대기

상세 설명

XPS OM 초기화

XPS 문서 API 참조

XML Paper Specification