Impresión de un OM XPS
Describe cómo enviar un OM XPS a una impresora como un documento XPS.
Para obtener instrucciones sobre cómo imprimir un OM XPS que contiene un documento XPS completo, vea Impresión de un OM XPS completo. Para contener un documento XPS, un OM XPS debe incluir los elementos enumerados en Creación de un OM XPS en blanco.
Para obtener instrucciones sobre cómo imprimir un OM XPS que se crea o procesa página a página, consulte Impresión incremental de un OM XPS.
Antes de usar estos ejemplos de código en el programa, lea la declinación de responsabilidades en Tareas comunes de programación de documentos XPS.
En este tema, aprenderá a realizar las siguientes tareas:
Impresión de un OM XPS completo
Cuando un OM XPS contiene un documento XPS completo, el método WriteToStream de la interfaz IXpsOMPackage puede enviar el contenido del OM XPS a una impresora o una cola de impresión.
Para detectar cuándo se ha completado el trabajo de impresión, cree un identificador de evento como se muestra en el ejemplo siguiente.
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.
}
Para imprimir un OM XPS completo:
- Cree un flujo de trabajo de impresión mediante una llamada a StartXpsPrintJob.
- Envíe el contenido del OM XPS al flujo mediante una llamada al método WriteToStream del paquete.
- Cierre la secuencia del trabajo de impresión llamando al método Close del flujo.
- Espere a que el trabajo de impresión indique que se ha completado.
- Compruebe el estado de finalización.
- Cierre y libere los recursos.
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
Impresión incremental de un OM XPS
Puede enviar los componentes de documento de un OM XPS a un trabajo de impresora de forma incremental, creando un flujo de trabajo de impresión XPS y pasando luego los componentes de documento individuales al flujo de trabajo de impresión de uno en uno. La secuencia en la que se envían los componentes del documento determina cómo aparecerán en el documento finalizado. Por lo tanto, antes de que un programa pueda llamar al código de este ejemplo, debe organizar correctamente los componentes del documento.
Antes de usar interfaces de OM XPS, inicialice COM en el subproceso como se muestra en el código de ejemplo siguiente.
HRESULT hr;
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
Para supervisar la finalización del trabajo de impresión, cree un identificador de evento como se muestra en el código de ejemplo siguiente.
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.
}
Cree un nuevo flujo de trabajo de impresión y un nuevo escritor de paquetes. Pase cada uno de los componentes del documento a los métodos de escritura de paquetes correspondientes en la misma secuencia que aparecerán en el documento terminado.
Inicie cada documento nuevo y agréguele páginas. Después de pasar todos los componentes del documento al flujo del trabajo de impresión, cierre la secuencia, espere a que se complete el trabajo de impresión y, a continuación, cierre y libere los recursos abiertos.
- Cree un flujo de trabajo de impresión mediante una llamada a StartXpsPrintJob.
- Cree un URI de parte para el elemento FixedDocumentSequence.
- Cree un nuevo escritor de paquetes en el flujo del trabajo de impresión.
- Para que cada documento se escriba:
- Cree un URI de parte para el elemento FixedDocument.
- Inicie un nuevo documento en el escritor de paquetes.
- Para cada página del documento actual, cree un URI de parte para el elemento FixedPage y agregue la página al escritor de paquetes.
- Una vez agregadas todas las páginas al escritor de paquetes, ciérrelo.
- Cierre el flujo del trabajo de impresión.
- Espere a que el trabajo finalice.
- Compruebe el estado de finalización.
- Cierre y libere los recursos abiertos.
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.
Cuando el programa está escribiendo los componentes del documento de forma incremental, como se muestra en este ejemplo, debe generar los nombres de los elementos de cada elemento de documento que envía al flujo de trabajo de impresión. En el ejemplo anterior, el URI del elemento FixedDocumentSequence se crea a partir de una cadena estática porque hay una y solo una parte en el documento XPS. El URI de cada elemento FixedPage y FixedDocument debe ser único dentro del documento XPS. La creación del URI de parte mediante el índice de estos componentes puede ayudar a garantizar que la cadena de URI resultante sea única en el documento 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;
}
Para obtener más información sobre la estructura de un documento XPS, vea XML Paper Specification.
Temas relacionados
-
Pasos siguientes
-
Usado en esta sección
-
Para obtener más información