Imprimer un modèle OM XPS

Décrit comment envoyer un modèle OM XPS à une imprimante sous la forme d’un document XPS.

Pour obtenir des instructions sur l’impression d’un modèle OM XPS contenant un document XPS complet, consultez imprimer un modèle d’objet XPS complet. Pour contenir un document XPS, un modèle d’objet XPS doit inclure les éléments listés dans créer un modèle d’objet XPS vide.

Pour obtenir des instructions sur l’impression d’un modèle d’objet XPS créé ou traité une seule page à la fois, consultez imprimer un modèle OMde manière incrémentielle.

Avant d’utiliser ces exemples de code dans votre programme, lisez l’exclusion de responsabilité dans les tâches de programmation de document XPS courantes.

Dans cette rubrique, vous allez apprendre à effectuer les tâches suivantes :

Quand un modèle d’objet XPS contient un document XPS complet, la méthode WriteToStream de l’interface IXpsOMPackage peut envoyer le contenu du modèle d’objet XPS à une imprimante ou à une file d’attente à l’impression.

Pour détecter le moment où le travail d’impression est terminé, créez un descripteur d’événement comme indiqué dans l’exemple suivant.

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

Pour imprimer un modèle d’objet XPS complet :

  1. Créez un flux de travail d’impression en appelant StartXpsPrintJob.
  2. Envoyez le contenu du modèle d’objet XPS au flux en appelant la méthode WriteToStream du package.
  3. Fermez le flux de travail d’impression en appelant la méthode Close du flux.
  4. Attendez que le travail d’impression signale qu’il est terminé.
  5. Vérifiez l’état d’achèvement.
  6. Fermer et libérer des ressources.
    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

Imprimer de manière incrémentielle un modèle OM XPS

Vous pouvez envoyer des composants de document d’un modèle OM XPS à un travail d’impression de manière incrémentielle, en créant un flux de travail d’impression XPS, puis en transmettant les composants de document individuels au flux de travail d’impression, l’un après l’autre. L’ordre dans lequel les composants de document sont envoyés détermine la façon dont ils apparaîtront dans le document terminé. Ainsi, avant qu’un programme puisse appeler le code dans cet exemple, il doit correctement organiser les composants de document.

Avant d’utiliser les interfaces du modèle d’objet XPS, initialisez COM dans le thread comme indiqué dans l’exemple de code suivant.

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

Pour surveiller l’achèvement du travail d’impression, créez un descripteur d’événement comme indiqué dans l’exemple de code suivant.

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

Créez un flux de travail d’impression et un nouvel enregistreur de package. Transmettez chacun des composants de document aux méthodes d’écriture de package correspondantes dans l’ordre dans lequel elles apparaissent dans le document terminé.

Démarrez chaque document nouveau, puis ajoutez-lui des pages. Après avoir passé tous les composants de document au flux de travail d’impression, fermez le flux, attendez la fin du travail d’impression, puis fermez et libérez les ressources ouvertes.

  1. Créez un flux de travail d’impression en appelant StartXpsPrintJob.
  2. Créez un URI de composant pour la partie FixedDocumentSequence.
  3. Créez un nouvel enregistreur de package sur le flux de travail d’impression.
  4. Pour chaque document à écrire :
    1. Créez un nouvel URI de composant pour la partie FixedDocument.
    2. Démarrez un nouveau document dans le writer de package.
    3. Pour chaque page du document actif, créez un URI de composant pour la partie FixedPage et ajoutez la page au writer de package.
  5. Une fois que toutes les pages ont été ajoutées au writer de package, fermez-la.
  6. Fermez le flux de travail d’impression.
  7. Attendez la fin du travail d’impression.
  8. Vérifiez l’état d’achèvement.
  9. Fermer et libérer des ressources ouvertes.
    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.

Quand le programme écrit les composants du document de manière incrémentielle, comme indiqué dans cet exemple, il doit générer les noms des parties de chaque partie document qu’il envoie au flux du travail d’impression. Dans l’exemple précédent, l’URI du composant FixedDocumentSequence est créé à partir d’une chaîne statique, car il n’y en a qu’une seule partie dans le document XPS. L’URI de chaque partie FixedPage et FixedDocument doit être unique dans le document XPS. La génération de l’URI du composant à l’aide de l’index de ces composants peut aider à garantir que la chaîne d’URI résultante est unique dans le document 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;
}

Pour plus d’informations sur la structure d’un document XPS, consultez la spécification Paper XML.

Next Steps

Écrire un modèle OM XPS dans un document XPS

Utilisé dans cette section

CoInitializeEx

CreateEvent

IOpcPartUri

IXpsOMPackage

IXpsOMPackageWriter

IXpsPrintJob

IXpsPrintJobStream

StartXpsPrintJob

WaitForSingleObject

Pour plus d’informations

Initialiser un modèle d’objet XPS

Informations de référence sur l’API de document XPS

XML Paper Specification