方法: XPS Print API を使用して印刷する

このトピックでは、 XPS Print API を使用して Windows アプリケーションから印刷する方法について説明します。

XPS 印刷 API を使用すると、ネイティブ Windows アプリケーションで XPS ドキュメントを印刷できます。 アプリケーションでは、XPS ドキュメント API を使用して XPS ドキュメントを作成できます。 一般的な XPS ドキュメント プログラミング タスクのヘルプ トピックでは、これを行う方法について説明します。 XPS ドキュメントが作成されると、アプリケーションは XPS Print API を使用して印刷できます。

XPS Print API を使用してアプリケーションからドキュメントを印刷するには、次の手順を実行します。

XPS 印刷 API には、印刷する XPS ドキュメントが必要です。 次の例では、XPS 印刷 API によってプリンターに送信されるときに XPS ドキュメントが作成されます。 また、XPS ドキュメント API を使用して XPS ドキュメント API を使用して XPS ドキュメントを保持するか、XPS OM を XPS ドキュメント として保存することで、プリンターに送信せずに XPS ドキュメントを作成することもできます。 XPS OM の使用の詳細については、「XPS ドキュメント API」を参照してください。

COM インターフェイスを初期化する

アプリケーションがまだ行っていない場合は、COM インターフェイスを初期化します。

    // Initialize the COM interface, if the application has not 
    //  already done so.
    if (FAILED(hr = CoInitializeEx(0, COINIT_MULTITHREADED)))
    {
        fwprintf(stderr, 
            L"ERROR: CoInitializeEx failed with HRESULT 0x%X\n", hr);
        return 1;
    }

完了イベントを作成する

完了イベントを作成します。 XPS Print API は、印刷スプーラーがアプリケーションからドキュメント全体を受信したときにアプリケーションに通知するために使用します。 XPS Print API では進行状況イベントもサポートされているため、アプリケーションは他のスプーリング アクティビティについて知ることができます。

        // Create the completion event
        completionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (!completionEvent)
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
            fwprintf(stderr, 
                L"ERROR: Could not create completion event: %08X\n", hr);
        }

XPS 印刷ジョブを開始する

StartXpsPrintJob を呼び出して XPS 印刷ジョブを開始します。 StartXpsPrintJob は、印刷するドキュメントをアプリケーションが送信するストリームを返します。

        // Start an XPS Print Job
        if (FAILED(hr = StartXpsPrintJob(
                    printerName,
                    NULL,
                    NULL,
                    NULL,
                    completionEvent,
                    NULL,
                    0,
                    &job,
                    &jobStream,
                    NULL
                    )))
        {
            fwprintf(stderr, 
                L"ERROR: Could not start XPS print job: %08X\n", hr);
        }

IXpsOMPackageWriter インターフェイスを作成する

StartXpsPrintJob によって返されるストリームで IXpsOMObjectFactory::CreatePackageWriterOnStream を呼び出して、IXpsOMPackageWriter インターフェイスを作成します。

    // Create an XPS OM Object Factory. If one has already been 
    //  created by the application, a new one is not necessary.
    if (SUCCEEDED(hr))
    {
        if (FAILED(hr = CoCreateInstance(
                __uuidof(XpsOMObjectFactory), 
                NULL,
                CLSCTX_INPROC_SERVER, 
                IID_PPV_ARGS(&xpsFactory))))
        {
            fwprintf(
                stderr, 
                L"ERROR: Could not create XPS OM Object Factory: %08X\n", 
                hr);
        }
    }
    // Create the Part URI for the Fixed Document Sequence. The
    //  Fixed Document Sequence is the top-level element in the
    //  package hierarchy of objects. There is one Fixed Document
    //  Sequence in an XPS document.
    //
    // The part name is not specified by the XML Paper Specification,
    //  however, the name used in this example is the part name
    //  used by convention.
    //
    if (SUCCEEDED(hr))
    {
        if (FAILED(hr = xpsFactory->CreatePartUri(
                    L"/FixedDocumentSequence.fdseq", 
                    &partUri)))
        {
            fwprintf(stderr, 
                L"ERROR: Could not create part URI: %08X\n", hr);
        }
    }

    // Create the package writer on the print job stream.
    if (SUCCEEDED(hr))
    {
        if (FAILED(hr = xpsFactory->CreatePackageWriterOnStream(
                    jobStream,
                    TRUE,
                    XPS_INTERLEAVING_ON,
                    partUri,
                    NULL,
                    NULL,
                    NULL,
                    NULL,
                    &packageWriter
                    )
                )
           )
        {
            fwprintf(
                stderr, 
                L"ERROR: Could not create package writer: 0x%X\n", 
                hr);
        }
    }

    // Release the part URI interface.
    if (partUri)
    {
        partUri->Release();
        partUri = NULL;
    }

この印刷ジョブの各ドキュメントについて、新しいドキュメントを開始し、そのドキュメントにページを追加します。

新しいドキュメントを開始する

IXpsOMPackageWriter::StartNewDocument を呼び出して、パッケージ ライターで新しいドキュメントを開始します。 このメソッドが呼び出されたときにドキュメントが開いている場合は、閉じられ、新しいドキュメントが開かれます。

    // Create the Part URI for the Fixed Document. The
    //  Fixed Document part contains the pages of the document. 
    //  There can be one or more Fixed Documents in an XPS document.
    //
    // The part name is not specified by the XML Paper Specification,
    //  however, the name format used in this example is the format 
    //  used by convention. The number "1" in this example must be 
    //  changed for each document in the package. For example, 1 
    //  for the first document, 2 for the second, and so on.
    //

    if (SUCCEEDED(hr))
    {
        if (FAILED(hr = xpsFactory->CreatePartUri(
                    L"/Documents/1/FixedDocument.fdoc", 
                    &partUri)))
        {
            fwprintf(
                stderr, 
                L"ERROR: Could not create part URI: %08X\n", 
                hr);
        }
    }

    // Start the new document.
    //
    //  If there was already a document started in this page,
    //  this call will close it and start a new one.
    if (SUCCEEDED(hr))
    {
        if (FAILED(hr = packageWriter->StartNewDocument(
                    partUri, 
                    NULL, 
                    NULL, 
                    NULL,
                    NULL)))
        {
            fwprintf(
                stderr, 
                L"ERROR: Could not start new document: 0x%X\n", 
                hr);
        }
    }
    
    // Release the part URI interface
    if (partUri)
    {
        partUri->Release();
        partUri = NULL;
    }

ページを追加する

IXpsOMPackageWriter::AddPage を呼び出して、各ドキュメントのページをアプリケーションからパッケージ ライターの新しいドキュメントに書き込みます。

注意

アプリケーションは、この手順の前にページを作成したと見なされます。 ドキュメント ページの作成とコンテンツの追加の詳細については、「 一般的な XPS ドキュメント プログラミング タスク」を参照してください。

 

    if (SUCCEEDED(hr))
    {
        // Add the current page to the document.
        if (FAILED(hr = packageWriter->AddPage(
                    xpsPage,
                    &pageSize,
                    NULL,
                    NULL,
                    NULL,
                    NULL
                    )))
        {
            fwprintf(
                stderr, 
                L"ERROR: Could not add page to document: %08X\n", 
                hr);
        }
    }

IXpsOMPackageWriter インターフェイスを閉じる

この印刷ジョブのすべてのドキュメントが書き込まれたら、 IXpsOMPackageWriter::Close を呼び出してパッケージを閉じます。

    if (SUCCEEDED(hr))
    {
        if (FAILED(hr = packageWriter->Close()))
        {
            fwprintf(
                stderr, 
                L"ERROR: Could not close package writer: %08X\n", 
                hr);
        }
    }

印刷ジョブ ストリームを閉じる

Close を呼び出して印刷ジョブ ストリームを閉じます。これにより、印刷ジョブ全体がアプリケーションによって送信されたことを印刷スプーラーに通知します。

    if (SUCCEEDED(hr))
    {
        if (FAILED(hr = jobStream->Close()))
        {
            fwprintf(
                stderr,
                L"ERROR: Could not close job stream: %08X\n",
                hr);
        }
    }
    else
    {
        // Only cancel the job if we succeeded in creating a job.
        if (job)
        {
            // Tell the XPS Print API that we're giving up.  
            //  Don't overwrite hr with the return from this function.
            job->Cancel();
        }
    }

完了イベントを待つ

印刷ジョブの完了イベントが発生するまで待ちます。

    if (SUCCEEDED(hr))
    {
        wprintf(L"Waiting for job completion...\n");

        if (WaitForSingleObject(completionEvent, INFINITE) != 
                                                    WAIT_OBJECT_0)
        {
            hr = HRESULT_FROM_WIN32(GetLastError());
            fwprintf(
                stderr, 
                L"ERROR: Wait for completion event failed: %08X\n", 
                hr);
        }
    }

完了イベントが通知されたら、 GetJobStatus を 呼び出してジョブの状態を取得します。

    if (SUCCEEDED(hr))
    {
        if (FAILED(hr = job->GetJobStatus(&jobStatus)))
        {
            fwprintf(
                stderr, 
                L"ERROR: Could not get job status: %08X\n", 
                hr);
        }
    }

    if (SUCCEEDED(hr))
    {
        switch (jobStatus.completion)
        {
            case XPS_JOB_COMPLETED:
                break;
            case XPS_JOB_CANCELLED:
                fwprintf(stderr, L"ERROR: job was cancelled\n");
                hr = E_FAIL;
                break;
            case XPS_JOB_FAILED:
                fwprintf(
                    stderr, 
                    L"ERROR: Print job failed: %08X\n", 
                    jobStatus.jobStatus);
                hr = E_FAIL;
                break;
            default:
                fwprintf(stderr, L"ERROR: unexpected failure\n");
                hr = E_UNEXPECTED;
                break;
        }
    }

リソースを解放する

ジョブの状態が完了したことを示したら、この印刷ジョブに使用されるインターフェイスとリソースを解放します。

    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;
    }