この記事では、Windows 印刷プロトコルについて説明し、複数のページを含むドキュメントを印刷する方法について説明します。 この記事では、次のトピックについて説明します。
印刷プロトコル
マルチページ ドキュメントを印刷するには、フレームワークとビューが次の方法で対話します。 まず、フレームワークで [印刷] ダイアログ ボックスが表示され、プリンターのデバイス コンテキストが作成され、CDC オブジェクトの StartDoc メンバー関数が呼び出されます。 次に、ドキュメントの各ページについて、フレームワークはCDC オブジェクトの StartPage メンバー関数を呼び出し、ページを印刷するようにビュー オブジェクトに指示し、EndPage メンバー関数を呼び出します。 特定のページを開始する前にプリンター モードを変更する必要がある場合、ビューは ResetDC を呼び出し、新しいプリンター モード情報を含む DEVMODE 構造体を更新します。 文書全体が印刷されると、フレームワークは EndDoc メンバー関数を呼び出します。
View クラス関数のオーバーライド
CView クラスは、印刷中にフレームワークによって呼び出される複数のメンバー関数を定義します。 ビュー クラスでこれらの関数をオーバーライドすることで、フレームワークの印刷ロジックとビュー クラスの印刷ロジックの間の接続を提供します。 次の表に、これらのメンバー関数を示します。
CView の印刷用のオーバーライド可能な関数
| 名前 | オーバーライドの理由 |
|---|---|
| OnPreparePrinting | [印刷] ダイアログ ボックスに値を挿入するには(特に文書の長さ) |
| OnBeginPrinting | フォントまたはその他の GDI リソースを割り当てるには |
| OnPrepareDC | 特定のページのデバイス コンテキストの属性を調整したり、印刷時の改ページを行ったりするには |
| OnPrint | 特定のページを印刷するには |
| OnEndPrinting | GDI リソースの割り当てを解除するには |
他の機能でも印刷関連の処理を行うことができますが、これらの機能は印刷プロセスを推進するものです。
次の図は、印刷プロセスに関連する手順を示し、 CViewの各印刷メンバー関数が呼び出される場所を示しています。 この記事の残りの部分では、これらの手順の大部分について詳しく説明します。 印刷プロセスのその他の部分については、「 GDI リソースの割り当て」を参照してください。
印刷ループ
改ページ
フレームワークは、印刷ジョブに関する情報の多くを CPrintInfo 構造体に格納します。
CPrintInfoの値の一部は改ページ位置付けに関連しています。これらの値には、次の表に示すようにアクセスできます。
CPrintInfo に格納されているページ番号情報
| メンバー変数または 関数名 |
参照されているページ番号 |
|---|---|
GetMinPage/SetMinPage |
ドキュメントの最初のページ |
GetMaxPage/SetMaxPage |
ドキュメントの最後のページ |
GetFromPage |
印刷する最初のページ |
GetToPage |
最後に印刷するページ |
m_nCurPage |
現在印刷中のページ |
ページ番号は 1 から始まります。つまり、最初のページには 0 ではなく 1 という番号が付けられます。 これらのメンバーと CPrintInfo の他のメンバーの詳細については、 MFC リファレンスを参照してください。
印刷プロセスの開始時に、フレームワークはビューの OnPreparePrinting メンバー関数を呼び出し、 CPrintInfo 構造体へのポインターを渡します。 アプリケーション ウィザードには、CViewの別のメンバー関数である DoPreparePrinting を呼び出すOnPreparePrintingの実装が用意されています。
DoPreparePrinting は、[印刷] ダイアログ ボックスを表示し、プリンター デバイス コンテキストを作成する関数です。
この時点で、アプリケーションはドキュメント内のページ数を認識しません。 ドキュメントの最初と最後のページの番号に既定値 1 と0xFFFFを使用します。 ドキュメントのページ数がわかっている場合は、OnPreparePrintingオーバーライドし、DoPreparePrintingに送信する前に、CPrintInfo構造体の [SetMaxPage]---brokenlink--(reference/cprintinfo-class.md#setmaxpage) を呼び出します。 これにより、ドキュメントの長さを指定できます。
DoPreparePrinting をクリックすると、[印刷] ダイアログ ボックスが表示されます。 返されると、 CPrintInfo 構造体には、ユーザーによって指定された値が含まれます。 ユーザーが選択したページ範囲のみを印刷する場合は、[印刷] ダイアログ ボックスで開始ページ番号と終了ページ番号を指定できます。 フレームワークは、CPrintInfo のGetFromPage関数とGetToPage関数を使用してこれらの値を取得します。 ユーザーがページ範囲を指定しない場合、フレームワークは GetMinPage と GetMaxPage を呼び出し、返された値を使用してドキュメント全体を印刷します。
印刷するドキュメントの各ページについて、フレームワークはビュー クラス OnPrepareDC と OnPrint の 2 つのメンバー関数を呼び出し、各関数に 2 つのパラメーター ( CDC オブジェクトへのポインターと CPrintInfo 構造体へのポインター) を渡します。 フレームワークは、OnPrepareDCとOnPrintを呼び出すたびに、CPrintInfo構造体のm_nCurPage メンバーに異なる値を渡します。 このように、フレームワークは、印刷するページをビューに指示します。
OnPrepareDC メンバー関数は、画面表示にも使用されます。 描画が行われる前に、デバイス コンテキストを調整します。
OnPrepareDC 印刷でも同様の役割を果たしますが、いくつかの違いがあります。1 つ目は、 CDC オブジェクトが画面のデバイス コンテキストではなくプリンター デバイス コンテキストを表し、2 番目に、 CPrintInfo オブジェクトが 2 番目のパラメーターとして渡されます。 (このパラメーターは、画面表示OnPrepareDC呼び出された場合は NULL です)。OnPrepareDCをオーバーライドして、印刷するページに基づいてデバイス コンテキストを調整します。 たとえば、ビューポートの原点とクリッピング領域を移動して、ドキュメントの適切な部分が確実に印刷されるようにすることができます。
OnPrint メンバー関数は、ページの実際の印刷を実行します。 「 既定の印刷の実行方法」では、 印刷を実行するために、フレームワークがプリンター デバイス コンテキストを使用して OnDraw を呼び出す方法を示します。 より正確には、フレームワークはCPrintInfo構造とデバイス コンテキストを使用してOnPrintを呼び出し、OnPrintはデバイス コンテキストをOnDrawに渡します。
OnPrintをオーバーライドして、画面表示ではなく、印刷時にのみ実行する必要があるレンダリングを実行します。 たとえば、ヘッダーまたはフッターを印刷する場合 (詳細については、 ヘッダーとフッター に関する記事を参照してください)。 次に、OnPrintのオーバーライドからOnDrawを呼び出して、画面表示と印刷の両方に共通するレンダリングを実行します。
OnDrawが画面表示と印刷の両方のレンダリングを行うという事実は、アプリケーションが WYSIWYG であることを意味します。ただし、WYSIWYG アプリケーションを作成していないとします。 たとえば、印刷に太字のフォントを使用し、コントロール コードを表示して画面に太字のテキストを示すテキスト エディターがあるとします。 このような状況では、 OnDraw を画面表示に厳密に使用します。
OnPrintをオーバーライドするときは、OnDrawの呼び出しを別の描画関数の呼び出しに置き換える必要があります。 この関数は、画面上に表示しない属性を使用して、文書を紙に表示する方法で描画します。
プリンター ページとドキュメント ページ
ページ番号を参照する場合、プリンターのページの概念とドキュメントのページの概念を区別することが必要な場合があります。 プリンターの観点から見て、ページは 1 枚の用紙です。 ただし、1 枚の用紙が必ずしも文書の 1 ページと等しいとは限りません。 たとえば、シートを折りたたむニュースレターを印刷する場合、1 枚の用紙に文書の最初のページと最後のページの両方が並んで含まれている場合があります。 同様に、スプレッドシートを印刷する場合、ドキュメントはページで構成されません。 代わりに、1 枚の用紙に行 1 ~ 20、列 6 ~ 10 が含まれる場合があります。
CPrintInfo 構造体のすべてのページ番号は、プリンター ページを参照します。 フレームワークは、プリンターを通過する用紙ごとに 1 回 OnPrepareDC と OnPrint を呼び出します。
OnPreparePrinting 関数をオーバーライドしてドキュメントの長さを指定する場合は、プリンター ページを使用する必要があります。 1 対 1 の対応 (つまり、1 つのプリンター ページが 1 つのドキュメント ページと等しい) がある場合、これは簡単です。 一方、ドキュメント ページとプリンター ページが直接対応していない場合は、それらの間で翻訳する必要があります。 たとえば、スプレッドシートを印刷することを検討します。
OnPreparePrintingをオーバーライドする場合は、スプレッドシート全体を印刷するために必要な用紙の数を計算し、CPrintInfoのSetMaxPageメンバー関数を呼び出すときにその値を使用する必要があります。 同様に、 OnPrepareDCをオーバーライドする場合は、 m_nCurPage をその特定のシートに表示される行と列の範囲に変換し、それに応じてビューポートの原点を調整する必要があります。
Print-Time 改ページ位置の変更
場合によっては、ビュー クラスがドキュメントが実際に印刷されるまでの時間を事前に把握していない場合があります。 たとえば、アプリケーションが WYSIWYG でないため、画面上のドキュメントの長さが印刷時の長さに対応していないとします。
これにより、ビュー クラスの OnPreparePrinting をオーバーライドするときに問題が発生します。ドキュメントの長さが分からないため、CPrintInfo 構造体のSetMaxPage関数に値を渡すことはできません。 ユーザーが [印刷] ダイアログ ボックスの使用を停止するページ番号を指定していない場合、フレームワークは印刷ループを停止するタイミングを認識しません。 印刷ループを停止するタイミングを判断する唯一の方法は、ドキュメントを印刷して、いつ終了するかを確認することです。 ビュー クラスは、印刷中にドキュメントの末尾を確認し、最後に達したときにフレームワークに通知する必要があります。
フレームワークは、ビュー クラスの OnPrepareDC 関数に依存して、停止するタイミングを伝えます。
OnPrepareDCを呼び出すたびに、フレームワークは m_bContinuePrinting というCPrintInfo構造体のメンバーをチェックします。 既定値は TRUE です。 残っている限り、フレームワークは印刷ループを続行します。
FALSE に設定すると、フレームワークは停止します。 印刷時の改ページ位置を変更するには、 OnPrepareDC をオーバーライドしてドキュメントの末尾に達したかどうかを確認し、 m_bContinuePrinting を FALSE に設定します。
OnPrepareDCの既定の実装では、現在のページが 1 より大きい場合、m_bContinuePrintingが FALSE に設定されます。 つまり、ドキュメントの長さが指定されていない場合、フレームワークではドキュメントが 1 ページ長であると見なされます。 その結果、基底クラスバージョンの OnPrepareDCを呼び出す場合は注意する必要があります。 基底クラスのバージョンを呼び出した後、 m_bContinuePrinting が TRUE になるとは想定しないでください。