XPS OM を印刷する
XPS OM を XPS ドキュメントとしてプリンターに送信する方法について説明します。
完全な XPS ドキュメントを含む XPS OM を印刷する手順については、「完全な XPS OM を印刷する」を参照してください。 XPS ドキュメントを含めるには、XPS OM を「空白の XPS OM を作成する」に一覧表示されている項目に含める必要があります。
作成または一度に 1 ページずつ処理された XPS OM を印刷する手順については、「XPS OM を増分印刷する」を参照してください。
これらのコード例をプログラムで使用する前に、「一般的な XPS ドキュメント プログラミング タスク」の免責事項をお読みください。
このトピックでは、次のタスクを実行する方法を学びます。
完全な XPS OM を印刷する
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 を印刷するには、次のようにします。
- StartXpsPrintJob を呼び出して、新しい印刷ジョブ ストリームを作成します。
- パッケージの WriteToStream メソッドを呼び出して、XPS OM の内容をストリームに送信します。
- ストリームの [閉じる] メソッドを呼び出して、印刷ジョブ ストリームを閉じます。
- 印刷ジョブが完了したことが通知されるまで待ちます。
- 完了状態を確認します。
- リソースを閉じて解放します。
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まで待ってから、開いているリソースを閉じて解放します。
- StartXpsPrintJob を呼び出して、新しい印刷ジョブ ストリームを作成します。
- FixedDocumentSequence パーツ用のパーツ URI を作成します。
- 印刷ジョブ ストリームで新しいパッケージ ライターを作成します。
- 書き込むドキュメントごとに、次の手順を実行します。
- FixedDocument パーツ用の新しいパーツ URI を作成します。
- パッケージ ライターで新しいドキュメントを開始します。
- 現在のドキュメントの各ページについて、FixedPage パーツのパーツ URI を作成し、パッケージ ライターにページを追加します。
- すべてのページがパッケージ ライターに追加されたら、それを閉じます。
- 印刷ジョブ ストリームを閉じます。
- 印刷ジョブが完了するまで待機します。
- 完了状態を確認します。
- 開いているリソースを閉じて解放します。
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」を参照してください。
関連トピック
-
次のステップ
-
このセクションで使用
-
詳細情報