次の方法で共有


TN030: 印刷および印刷プレビューのカスタマイズ

次のテクニカル ノートは、最初にオンライン ドキュメントに含まれてから更新されていません。 その結果、一部の手順やトピックが古くなっているか、正しくない可能性があります。 最新情報については、オンライン ドキュメント インデックスで関心のあるトピックを検索することをお勧めします。

このメモでは、印刷と印刷プレビューをカスタマイズするプロセスについて説明し、 CView で使用されるコールバック ルーチンの目的と、 CPreviewViewのコールバック ルーチンとメンバー関数について説明します。

問題

MFC は、ほとんどの印刷および印刷プレビューのニーズに対応する完全なソリューションを提供します。 ほとんどの場合、ビューを印刷してプレビューできるようにするために、追加のコードはほとんど必要ありません。 ただし、開発者側で多大な労力を要する印刷を最適化する方法があり、一部のアプリケーションでは、印刷プレビュー モードに特定のユーザー インターフェイス要素を追加する必要があります。

効率的な印刷

MFC アプリケーションが標準メソッドを使用して出力すると、Windows はすべてのグラフィカル デバイス インターフェイス (GDI) 出力呼び出しをメモリ内メタファイルに転送します。 EndPageが呼び出されると、プリンターが 1 ページを印刷するために必要な物理バンドごとにメタファイルが 1 回再生されます。 このレンダリング中、GDI は頻繁に中止プロシージャを照会し、続行する必要があるかどうかを判断します。 通常、中止プロシージャを使用すると、ユーザーが印刷ダイアログを使用して印刷ジョブを中止できるように、メッセージを処理できます。

残念ながら、これにより印刷プロセスが遅くなる可能性があります。 アプリケーションでの印刷が標準の手法を使用して実現できるよりも高速である必要がある場合は、手動バンディングを実装する必要があります。

手動でバンド化するには、 OnPrint がページごとに複数回呼び出されるように (バンドごとに 1 回) 印刷ループを実装する必要があります。 印刷ループは、viewprnt.cppの OnFilePrint 関数に実装されます。 CView派生クラスでは、この関数をオーバーロードして、print コマンドを処理するためのメッセージ マップ エントリが print 関数を呼び出すようにします。 OnFilePrint ルーチンをコピーし、印刷ループを変更してバンディングを実装します。 印刷するページのセクションに基づいて描画を最適化できるように、印刷機能に縞模様の四角形を渡すこともできます。

次に、バンドの描画中に QueryAbort を頻繁に呼び出す必要があります。 それ以外の場合、Abort プロシージャは呼び出されず、ユーザーは印刷ジョブを取り消すことができません。

基本的に、印刷プレビューは、ディスプレイをプリンターのエミュレーションに変換しようとします。 既定では、メイン ウィンドウのクライアント領域は、ウィンドウ内に 1 つまたは 2 つのページを完全に表示するために使用されます。 ユーザーはページの領域を拡大して、より詳細に表示できます。 追加のサポートにより、ユーザーはプレビュー モードでドキュメントの編集を許可される場合もあります。

印刷プレビューのカスタマイズ

このメモでは、印刷プレビューの変更の 1 つの側面 (プレビュー モードへの UI の追加) のみを扱います。 その他の変更も可能ですが、このような変更は、この説明の範囲外です。

プレビュー モードに UI を追加するには

  1. CPreviewViewからビュー クラスを派生させます。

  2. 必要な UI 側面のコマンド ハンドラーを追加します。

  3. 表示に視覚的な側面を追加する場合は、 OnDraw をオーバーライドし、 CPreviewView::OnDraw呼び出した後に描画を実行します。

OnFilePrintPreview

これは、印刷プレビューのコマンド ハンドラーです。 既定の実装は次のとおりです。

void CView::OnFilePrintPreview()
{
    // In derived classes, implement special window handling here
    // Be sure to Unhook Frame Window close if hooked.

    // must not create this on the frame. Must outlive this function
    CPrintPreviewState* pState = new CPrintPreviewState;

    if (!DoPrintPreview(AFX_IDD_PREVIEW_TOOLBAR, this,
        RUNTIME_CLASS(CPreviewView), pState))
    {
        // In derived classes, reverse special window handling
        // here for Preview failure case

        TRACE0("Error: DoPrintPreview failed");
        AfxMessageBox(AFX_IDP_COMMAND_FAILURE);
        delete pState;  // preview failed to initialize, delete State now
    }
}

DoPrintPreview では、アプリケーションのメイン ウィンドウが非表示になります。 ステータス バーなどのコントロール バーは、pState->dwStates メンバーで指定することで保持できます (これはビット マスクであり、個々のコントロール バーのビットは AFX_CONTROLBAR_MASK( AFX_IDW_MYBAR) で定義されます)。 ウィンドウ pState->nIDMainPane は、自動的に非表示になり、再表示されるウィンドウです。 DoPrintPreview では、標準のプレビュー UI 用のボタン バーが作成されます。 他のウィンドウの非表示や表示など、特別なウィンドウ処理が必要な場合は、 DoPrintPreview が呼び出される前に行う必要があります。

既定では、印刷プレビューが完了すると、コントロール バーが元の状態に戻り、メイン ウィンドウが表示されます。 特別な処理が必要な場合は、 EndPrintPreviewのオーバーライドで行う必要があります。 DoPrintPreview失敗した場合は、特別な処理も指定します。

DoPrintPreview は次を使用して呼び出されます。

  • プレビュー ツール バーのダイアログ テンプレートのリソース ID。

  • 印刷プレビューの印刷を実行するビューへのポインター。

  • Preview View クラスのランタイム クラス。 これは DoPrintPreview で動的に作成されます。

  • CPrintPreviewState ポインター。 CPrintPreviewState 構造体 (または、アプリケーションでより多くの状態を保持する必要がある場合は派生構造体) をフレームに作成 しないでください 。 DoPrintPreview はモードレスであり、EndPrintPreview が呼び出されるまでこの構造体は存続する必要があります。

    印刷のサポートに別のビューまたはビュー クラスが必要な場合は、そのオブジェクトへのポインターを 2 番目のパラメーターとして渡す必要があります。

EndPrintPreview

これは、印刷プレビュー モードを終了するために呼び出されます。 多くの場合、印刷プレビューで最後に表示されたドキュメント内のページに移動することをお勧めします。 EndPrintPreview は、それを行うアプリケーションのチャンスです。 pInfo->m_nCurPage メンバーは、最後に表示されたページ (2 ページが表示された場合は左端) であり、ポインターはユーザーが関心を持っていたページ上の場所に関するヒントです。 アプリケーションのビューの構造はフレームワークでは不明であるため、選択したポイントに移動するコードを指定する必要があります。

ほとんどのアクションは、 CView::EndPrintPreviewを呼び出す前に実行する必要があります。 この呼び出しは、 DoPrintPreview の効果を反転し、pView、pDC、および pInfo を削除します。

// Any further cleanup should be done here.
CView::EndPrintPreview(pDC, pInfo, point, pView);

CWinApp::OnFilePrintSetup

これは、[印刷設定] メニュー項目にマップする必要があります。 ほとんどの場合、実装をオーバーライドする必要はありません。

ページの命名

もう 1 つの問題は、ページ番号と順序です。 単純なワード プロセッサの種類のアプリケーションの場合、これは簡単な問題です。 ほとんどの印刷プレビュー システムでは、印刷された各ページがドキュメント内の 1 つのページに対応することを前提としています。

一般化されたソリューションを提供する場合、考慮すべき点がいくつかあります。 CAD システムを想像してみてください。 ユーザーは、複数の E サイズシートをカバーする図面を持っています。 E サイズ (または小さい拡大/縮小) のプロッターでは、ページ番号は単純な場合と同じになります。 ただし、レーザー プリンターでは、1 枚あたり 16 ページの A サイズの印刷を行う場合、印刷プレビューでは "ページ" と見なされます

入門段落の状態として、印刷プレビューはプリンターのように動作します。 そのため、選択されている特定のプリンターから何が出てくるかをユーザーに表示します。 各ページに印刷される画像は、ビューによって決まります。

CPrintInfo構造体のページ説明文字列は、ページ番号をページごとに 1 つの番号として表すことができる場合にユーザーに表示する手段を提供します (「ページ 1」または「ページ 1-2」のように)。 この文字列は、 CPreviewView::OnDisplayPageNumberの既定の実装で使用されます。 別の表示が必要な場合は、"Sheet1、Sections A、B" など、この仮想関数をオーバーライドして指定できます。

こちらも参照ください

番号別テクニカル ノート
カテゴリ別テクニカル ノート