次の方法で共有


XPS OM を印刷する

XPS OM を XPS ドキュメントとしてプリンターに送信する方法について説明します。

完全な XPS ドキュメントを含む XPS OM を印刷する手順については、「完全な XPS OM を印刷する」を参照してください。 XPS ドキュメントを含めるには、XPS OM を「空白の XPS OM を作成する」に一覧表示されている項目に含める必要があります。

作成または一度に 1 ページずつ処理された 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. ストリームの [閉じる] メソッドを呼び出して、印刷ジョブ ストリームを閉じます。
  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 印刷ジョブ ストリームを作成し、個々のドキュメント コンポーネントを一度に 1 つずつ印刷ジョブ ストリームに渡すことで、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.
    }

新しい印刷ジョブ ストリームと新しいパッケージ ライターを作成します。 各ドキュメント コンポーネントを、完了したドキュメントに表示されるのと同じ順序で、対応するパッケージ ライター メソッドに渡します。

各ドキュメントを新規に開始し、ページを追加します。 すべてのドキュメント コンポーネントを印刷ジョブ ストリームに渡した後、ストリームを閉じ、印刷ジョブが完了するlまで待ってから、開いているリソースを閉じて解放します。

  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 ドキュメントにはそのようなパーツが 1 つだけ存在するためです。 各 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 Paper Specification」を参照してください。

次のステップ

XPS OM を XPS ドキュメントに書き込む

このセクションで使用

CoInitializeEx

CreateEvent

IOpcPartUri

IXpsOMPackage

IXpsOMPackageWriter

IXpsPrintJob

IXpsPrintJobStream

StartXpsPrintJob

WaitForSingleObject

詳細情報

XPS OM の初期化

XPS ドキュメント API リファレンス

XML Paper Specification