Imprimer un OM XPS
Décrit comment envoyer un OM XPS à une imprimante en tant que document XPS.
Pour obtenir des instructions sur l’impression d’un OM XPS qui contient un document XPS complet, consultez Imprimer un OM XPS complet. Pour contenir un document XPS, un OM XPS doit inclure les éléments répertoriés dans Créer un OM XPS vide.
Pour obtenir des instructions sur l’impression d’un OM XPS en cours de création ou de traitement page à page, consultez Imprimer de manière incrémentielle un OM XPS.
Avant d’utiliser les exemples de code suivants dans votre programme, lisez l’exclusion de responsabilité dans les Tâches courantes de programmation de documents XPS.
Dans cette rubrique, vous allez effectuer les tâches suivantes :
Imprimer un OM XPS complet
Lorsqu’un OM XPS contient un document XPS complet, la méthode WriteToStream de l’interface IXpsOMPackage peut envoyer le contenu de l’OM XPS à une imprimante ou à une file d’attente à l’impression.
Pour détecter la fin du travail d’impression, créez un handle d’événement, comme illustré 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 OM XPS complet :
- Créez un flux de travail d’impression en appelant StartXpsPrintJob.
- Envoyez le contenu de l’OM XPS au flux en appelant la méthode WriteToStream du package.
- Fermez le flux de travail d’impression en appelant la méthode Close du flux.
- Attendez que le travail d’impression indique qu’il est terminé.
- Vérifiez l’état d’achèvement.
- Fermez et libérez les 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 OM XPS
Vous pouvez envoyer les composants de document d’un OM XPS à un travail d’imprimante de manière incrémentielle, en créant un flux de travail d’impression XPS, puis en passant les composants de document individuels au flux de travail d’impression, un par un. La séquence dans laquelle les composants du document sont envoyés détermine comment ils apparaissent dans le document terminé. Par conséquent, avant qu’un programme puisse appeler le code dans cet exemple, il doit organiser correctement les composants du document.
Avant d’utiliser des interfaces d’OM XPS, initialisez COM dans le thread, comme illustré 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 handle d’événement, comme illustré 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’enregistreur de package correspondantes dans la même séquence qu’ils apparaîtront dans le document terminé.
Démarrez chaque document nouveau, puis ajoutez-y des pages. Après avoir transmis tous les composants de document au flux de travail d’impression, fermez le flux, attendez que le travail d’impression se termine, puis fermez et libérez les ressources ouvertes.
- Créez un flux de travail d’impression en appelant StartXpsPrintJob.
- Créez un URI de composant pour le composant FixedDocumentSequence.
- Créez un enregistreur de package sur le flux de travail d’impression.
- Pour que chaque document soit écrit :
- Créez un URI de composant pour le composant FixedDocument.
- Démarrez un nouveau document dans l’enregistreur de package.
- Pour chaque page du document actif, créez un URI de composant pour le composant FixedPage et ajoutez la page à l’enregistreur de package.
- Une fois que toutes les pages ont été ajoutées à l’enregistreur de package, fermez-le.
- Fermez le flux de travail d’impression.
- Veuillez attendre l’achèvement du travail d'impression.
- Vérifiez l’état d’achèvement.
- Fermez et libérez les 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.
Lorsque le programme écrit les composants de document de manière incrémentielle, comme illustré dans cet exemple, il doit générer les noms des composants pour chaque composant de document qu’il envoie au flux de travail d’impression. Dans l’exemple précédent, l’URI du composant FixedDocumentSequence est créé à partir d’une chaîne statique, car il existe un et un seul composant de ce type dans le document XPS. L’URI de chaque composant FixedPage et FixedDocument doit être unique dans le document XPS. La création de l’URI de composant à l’aide de l’index de ces composants peut vous 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 XML Paper Specification.
Rubriques connexes
-
Étapes suivantes
-
Utilisé dans cette section
-
Pour plus d'informations