共用方式為


TN030:自訂列印和預覽列印

注意

下列技術提示自其納入線上文件以來,未曾更新。 因此,有些程序和主題可能已過期或不正確。 如需最新資訊,建議您在線上文件索引中搜尋相關的主題。

此附注描述自訂列印和預覽列印的程式,並描述 中 CView 所使用的回呼常式以及 的回呼常式和成員函式的目的 CPreviewView

問題

MFC 提供適用于大多數列印和預覽列印需求的完整解決方案。 在大部分情況下,只需要一些額外的程式碼,才能列印和預覽檢視。 不過,有一些方法可將列印優化,需要在開發人員的一部分投入大量精力,而某些應用程式需要將特定使用者介面元素新增至預覽列印模式。

有效率的列印

當 MFC 應用程式使用標準方法列印時,Windows 會將所有圖形化裝置介面 (GDI) 輸出呼叫導向記憶體內部中繼檔。 呼叫 時 EndPage ,Windows 會針對印表機需要列印一頁的每個實體頻帶播放中繼檔一次。 在此轉譯期間,GDI 經常會查詢中止程式,以判斷是否應該繼續。 通常中止程式允許處理訊息,讓使用者可以使用列印對話方塊中止列印工作。

不幸的是,這可能會減緩列印程式。 如果應用程式中的列印速度必須比使用標準技術快,您必須實作手動帶狀。

若要手動帶狀,您必須重新實作列印迴圈,讓 OnPrint 每個頁面呼叫多次(每個帶一次)。 print 迴圈會在 viewprnt.cpp 的 OnFilePrint 函式中實作。 在 CView 衍生類別中,您會多載此函式,讓訊息對應專案處理列印命令會呼叫您的 print 函式。 OnFilePrint複製常式並變更列印迴圈以實作帶狀。 您可能也會想要將帶狀矩形傳遞至列印函式,以便根據列印的頁面區段優化繪圖。

其次,在繪製帶狀時,您必須經常呼叫 QueryAbort 。 否則,不會呼叫中止程式,而且使用者將無法取消列印工作。

基本上,預覽列印會嘗試將顯示器轉換成印表機的模擬。 根據預設,主視窗的工作區是用來在視窗內完整顯示一或兩個頁面。 使用者可以放大頁面的區域,以更詳細地查看它。 有了額外的支援,使用者甚至可以在預覽模式中編輯檔。

自訂預覽列印

此附注只會處理修改預覽列印的一個方面:將 UI 新增至預覽模式。 可能進行其他修改,但這類變更已超過此討論的範圍。

將 UI 新增至預覽模式

  1. CPreviewView 衍生檢視類別。

  2. 為您想要的 UI 層面新增命令處理常式。

  3. 如果您要將視覺層面新增至顯示,請在呼叫 CPreviewView::OnDraw 之後覆寫 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 是以:

  • 預覽工具列之對話方塊範本的資源識別碼。

  • 要執行預覽列印列印之檢視的指標。

  • Preview View 類別的執行時間類別。 這會在 DoPrintPreview 中動態建立。

  • CPrintPreviewState 指標。 請注意,CPrintPreviewState 結構(如果應用程式需要保留更多狀態,則衍生結構)不得 在畫面上建立。 DoPrintPreview 是無模式的,而且這個結構必須生存,直到呼叫 EndPrintPreview 為止。

    注意

    如果列印支援需要個別的檢視或檢視類別,該物件的指標應該傳遞為第二個參數。

EndPrintPreview

這會呼叫 以終止預覽列印模式。 通常最好移至上次在預覽列印中顯示的檔中的頁面。 EndPrintPreview 是應用程式執行此動作的機會。 pInfo-m_nCurPage > 成員是上次顯示的頁面(如果顯示兩個頁面,最左邊),而指標是使用者感興趣的頁面上位置的提示。 由於架構中應用程式檢視的結構未知,因此您必須提供程式碼以移至所選的點。

您應該先執行大部分的動作,再呼叫 CView::EndPrintPreview 。 此呼叫會反轉 和 刪除 pView、pDC 和 pInfo 的效果 DoPrintPreview

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

CWinApp::OnFilePrintSetup

這必須對應至 [列印設定] 功能表項目。 在大部分情況下,不需要覆寫實作。

Page Nomenclature

另一個問題是頁碼和順序。 對於簡單的字處理器類型應用程式,這是一個直接的問題。 大部分的預覽列印系統都假設每個列印的頁面都對應至檔中的一頁。

嘗試提供一般化解決方案時,需要考慮數件事。 想像一下 CAD 系統。 使用者有涵蓋數張 E 大小工作表的繪圖。 在 E 大小(或較小、縮放的)繪圖器上,頁碼會如同簡單案例一樣。 但在雷射印表機上,每張紙張列印 16 個 A 大小的頁面,預覽列印會考慮「頁面」

如介紹段落所述,預覽列印會像印表機一樣。 因此,使用者會看到會從選取的特定印表機中取出的內容。 由檢視決定每個頁面上所列印的影像。

結構中的 CPrintInfo 頁面描述字串會提供一種方法,以表示每個頁面的一個數位時向使用者顯示頁碼(如「第 1 頁」或「第 1-2 頁」所示)。 預設的 實作 CPreviewView::OnDisplayPageNumber 會使用此字串。 如果需要不同的顯示器,可能會覆寫此虛擬函式以提供,例如「Sheet1、Sections A、B」。

另請參閱

依編號顯示的技術提示
依分類區分的技術提示