次の方法で共有


マルチページ ドキュメント

更新 : 2007 年 11 月

ここでは、Windows の印刷プロトコル、およびマルチページ ドキュメントを印刷する方法について説明します。ここでは、次のトピックについて説明します。

  • 印刷プロトコル

  • ビュー クラス関数のオーバーライド

  • 改ページ調整

  • プリンタ ページとドキュメント ページ

  • 印刷時のページ数チェック

印刷プロトコル

マルチページ ドキュメントを印刷するために、フレームワークとビュー クラスは次の方法でやり取りを行います。まず、フレームワークが [印刷] ダイアログ ボックスを表示し、プリンタ用のデバイス コンテキストを作成してから、CDC オブジェクトの StartDoc メンバ関数を呼び出します。次に、ドキュメントの各ページごとに、フレームワークは CDC オブジェクトの StartPage メンバ関数を呼び出し、ビュー オブジェクトにページ印刷を始めるよう指示してから、EndPage メンバ関数を呼び出します。特定のページの印刷を開始する前にプリンタ モードを変更する場合は、ビューによって ResetDC が呼び出されます。ResetDC では、新しいプリンタ モード情報を格納している DEVMODE 構造体が更新されます。ドキュメント全体の印刷が完了すると、フレームワークは EndDoc メンバ関数が呼び出します。

ビュー クラス関数のオーバーライド

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 構造体に渡されます。アプリケーション ウィザードが提供する OnPreparePrinting メンバ関数は、CView クラスの別の DoPreparePrinting メンバ関数を呼び出します。DoPreparePrinting メンバ関数は、[印刷] ダイアログ ボックスを表示し、プリンタ デバイス コンテキストを作成します。

この時点では、アプリケーションにはドキュメントのページ数がわかりません。ドキュメントの最初のページに 1、最後のページには 0xFFFF が、それぞれの既定値として適用されます。ドキュメントのページ数がわかっている場合は、OnPreparePrinting をオーバーライドして、CPrintInfo 構造体の SetMaxPage を呼び出してから DoPreparePrinting に送ります。これによって、ドキュメントの長さを指定できるようになります。

次に、DoPreparePrinting は [印刷] ダイアログ ボックスを表示します。この関数から戻ると、ユーザーがダイアログ ボックスで指定した値が CPrintInfo 構造体に格納されています。選択範囲内のページのみを印刷する場合、[印刷] ダイアログ ボックスで開始ページ番号と終了ページ番号を指定できます。フレームワークは、CPrintInfoGetFromPage 関数と GetToPage 関数でその値を取得します。ページ範囲を指定しない場合は、GetMinPage および GetMaxPage が呼び出され、返された値を使用してすべてのページを印刷します。

印刷するドキュメントの各ページで、ビュー クラスの 2 つのメンバ関数、OnPrepareDCOnPrint が呼び出され、CDC オブジェクトへのポインタと CPrintInfo 構造体へのポインタが、各関数の 2 つのパラメータとして渡されます。OnPrepareDCOnPrint が呼び出されるたびに、CPrintInfo 構造体の m_nCurPage メンバで異なる値が渡されます。このように、フレームワークでは印刷するページがビューに伝えられます。

OnPrepareDC メンバ関数は画面表示にも使用されます。描画が表示される前に、デバイス コンテキストを調整します。OnPrepareDC は印刷の場合と似た役割を果たしますが、相違点が 2 つあります。1 つ目は、CDC オブジェクトは画面デバイス コンテキストではなく、プリンタ デバイス コンテキストを表すことです。2 つ目は、CPrintInfo オブジェクトが 2 番目の引数として渡されることです(この引数は、画面表示に OnPrepareDC が呼び出された場合は NULL です)。OnPrepareDC をオーバーライドし、印刷するページに基づいてデバイス コンテキストを調整します。たとえば、ビューポートの原点とクリップ領域を移動して、ドキュメントの必要な部分を印刷できます。

OnPrint メンバ関数によって、実際にページが印刷されます。「既定の印刷プロセス」では、印刷を実行するプリンタ デバイス コンテキストでフレームワークがどのように OnDraw を呼び出すかを説明します。具体的には、フレームワークは CPrintInfo 構造体およびデバイス コンテキストで OnPrint を呼び出し、OnPrint はデバイス コンテキストを OnDraw に渡します。画面表示は変えずに印刷時にだけレンダリングを実行するには、OnPrint をオーバーライドします。たとえば、ヘッダーまたはフッターを印刷する場合などがあります。詳細については、「ヘッダーとフッター」を参照してください。次に、OnPrint のオーバーライドから OnDraw を呼び出し、画面表示および印刷に共通のレンダリングを実行します。

OnDraw 関数が画面表示および印刷の両方でレンダリングを実行することで、アプリケーションは WYSIWYG (What You See Is What You Get) になります。一方、作成するアプリケーションが WYSIWYG ではない場合を考えてみます。たとえば、印刷には太字のフォントを使用し、画面でも制御コードを使用して太字の文字を表示するテキスト エディタがあるとします。このような場合、OnDraw を画面表示専用に使用します。つまり、OnPrint 関数をオーバーライドするときに、OnDraw の呼び出しの代わりに別の描画関数を呼び出します。このような描画関数は、画面には表示されない属性を用いて、紙に印刷するとおりにドキュメントを描画します。

プリンタ ページとドキュメント ページ

ページ番号を参照するときに、プリンタのページの概念とドキュメントのページの概念を区別しなければならない場合があります。プリンタのページは 1 枚の紙を意味します。しかし、1 枚の紙が常にドキュメントの 1 ページに相当するとは限りません。たとえば、2 つ折りのニュースレターを印刷する場合は、1 枚の紙の片側ずつに、ドキュメントの最初のページと最後のページが並ぶこともあります。同様に、スプレッドシートの印刷では、ドキュメントの構成自体がページ単位ではありません。たとえば、1 枚の紙に 1 行目から 20 行目および 6 列目から 10 列目までが範囲として入ることもあります。

CPrintInfo 構造体に含まれるすべてのページ番号は、プリンタでのページを表します。フレームワークは、用紙が 1 枚プリンタに送られるたびに OnPrepareDC および OnPrint を呼び出します。OnPreparePrinting 関数をオーバーライドしてドキュメントの長さを指定する場合は、プリンタのページを指定します。一対一で対応している場合、つまり、プリンタの 1 ページとドキュメントの 1 ページが同じ場合は、作業は簡単です。一方、プリンタの 1 ページとドキュメントの 1 ページが対応していない場合は、両者の間で変換が必要です。たとえば、スプレッドシートを印刷するとします。OnPreparePrinting をオーバーライドするときに、スプレッドシートの印刷に必要な枚数を計算し、CPrintInfoSetMaxPage メンバ関数を呼び出すときにその値を使用します。また、OnPrepareDC をオーバーライドするときは、m_nCurPage を特定のシートに表示される行および列の範囲に変換し、それに合わせてビューポートの原点を調整する必要があります。

印刷時のページ数チェック

実際に印刷されるまで、ドキュメントの長さがビュー クラスであらかじめ認識されていない場合もあります。たとえば、アプリケーションが WYSIWYG ではない場合、画面上のドキュメントの長さは印刷時の長さと一致しません。

これが原因で、ビュー クラスの OnPreparePrinting メンバ関数をオーバーライドする時に問題が発生します。つまり、ドキュメントの長さがわからないため、SetMaxPage 関数で CPrintInfo 構造体に値を指定できません。ユーザーが印刷を停止するページ番号を [印刷] ダイアログ ボックスで指定しない限り、フレームワークでは印刷ループを停止するタイミングを認識できません。印刷ループを停止するタイミングを決める唯一の方法は、ドキュメントの終わりを確認することです。ビュー クラスでは、印刷中にドキュメントの終わりを確認して、フレームワークに終了を通知する必要があります。

フレームワークは、ビュー クラスの OnPrepareDC 関数によって終了のタイミングを通知します。OnPrepareDC の呼び出しのたびに、m_bContinuePrinting と呼ばれる CPrintInfo 構造体のメンバがチェックされます。既定値は TRUE です。既定値のままの場合、フレームワークは印刷ループを続行します。FALSE に設定すると、印刷ループは停止します。印刷時のページ数チェックを実行するには、OnPrepareDC をオーバーライドしてドキュメントの最後かどうかをチェックし、ドキュメントの終わりで m_bContinuePrintingFALSE に設定します。

現在のページが 1 より後の場合、OnPrepareDC の既定の実装では、m_bContinuePrintingFALSE に設定されています。これは、ドキュメントの長さが指定されていない場合に、フレームワークではドキュメントが 1 ページの長さであると見なされることを意味します。このため、OnPrepareDC の基本クラスを呼び出す場合には注意が必要です。基本クラス バージョンを呼び出した後で m_bContinuePrintingTRUE になるとは限りません。

さらに詳しくは次のトピックをクリックしてください

参照

参照

印刷

CView クラス

CDC クラス