在Windows應用程序開發(fā)過程中,實現(xiàn)文檔打印功能是每一個開發(fā)人員都不得不面對的問題。在使用Visual C++6.0這一開發(fā)工具的情況下,雖然它的AppWizard生成的應用程序框架中缺省地包括打印功能,但是如何具體實現(xiàn)打印功能的確是一件非常繁雜的事情,尤其是要實現(xiàn)文檔的分頁打印,更是一個讓很多初學者感到困惑的問題。筆者結(jié)合自己學習體會,談一談如何實現(xiàn)文檔的分頁打印功能,希望可以對廣大讀者朋友們起到一定的幫助。
一、MFC程序默認的打印流程
Visual C++6.0的應用程序向?qū)ВˋppWizard)生成的應用程序具備了實現(xiàn)打印功能的基本框架,當用戶從菜單中選擇Print命令時,應用程序就用ID_FILE_PRINT命令消息調(diào)用程序視圖類的缺省處理函數(shù)OnFilePrint()來開始打印過程,并創(chuàng)建用語打印的設備環(huán)境,來滿足應用程序特定的需要。其中要重載應用程序視圖類的幾個相應函數(shù),其函數(shù)表如圖一所示:
函數(shù) |
說明 |
OnBeginPrinting() |
重載此函數(shù)來創(chuàng)建在打印文檔時所需的資源,如字體等。在此也可以設置最大頁數(shù)。 |
OnDraw() |
該函數(shù)提供三重服務,在框架窗口、預覽窗口和打印機上顯示數(shù)據(jù),具體在哪里顯示,依賴于作為函數(shù)參數(shù)傳遞的設備環(huán)境。 |
OnEndPrinting() |
重載此函數(shù)用來釋放在OnBeginPrinting()中創(chuàng)建的資源。 |
OnPrepareDC() |
重載此函數(shù)來修改用于顯示或打印文檔的設備環(huán)境,可以在此處理換頁。 |
OnPreparePrinting() |
提供打印文檔的最大頁數(shù),如果在此不設置頁數(shù),必須在OnBeiginPrinting()中設置。 |
OnPrint() |
提供附加打印服務,如在Cview::OnDraw()函數(shù)中不提供的打印頁眉、頁腳。 |
表一、實現(xiàn)打印功能需要重載的幾個CView類成員函數(shù)
OnFilePrint()函數(shù)一開始就調(diào)用OnPreparePrinting()函數(shù),該函數(shù)缺省時則調(diào)用DoPreparePrinting()函數(shù)來顯示打印對話框,創(chuàng)建的OnPreparePrinting()程序如下:
BOOL CmyView::OnpreparePrinting(CprintInfo *pInfo) { //default preparetion return DoPreparePrinting(pInfo); } |
程序中,OnPreparePrinting()提供一個指向CprintInfo對象的指針參數(shù),使用此對象,應用程序能夠獲取關(guān)于打印作業(yè)的信息,同時對屬性(例如最大頁數(shù))進行初始化。DoPreparePrinting()顯示對話框時,由用戶設置CprintInfo類的許多數(shù)據(jù)成員變量供應用程序使用或再設置,即用于創(chuàng)建整個打印的設備環(huán)境。
打印過程都要用到CprintInfo結(jié)構(gòu),它里面保存了打印任務的信息。OnPreparePrinting()重載是為了指明打印文件的長度。在調(diào)用Cview::DoPreparePrinting()之前,可用其參數(shù)來修改CprintInfo結(jié)構(gòu)。重載OnPreparePrinting()還可以使用CprintInfo結(jié)構(gòu)的成員函數(shù)SetMaxPage()、SetMinPage()來設置文檔的最大、最小頁數(shù)。當把CprintInfo結(jié)構(gòu)中表明文檔是否被直接打印標志變量m_bDirect設置為TRUE時,調(diào)用DoPreparePrinting()就不再顯示打印對話框。此時,由于沒有打印對話框,可以用SetToPage()和SetFromPage()設置打印的起始頁。
接下來,打印程序調(diào)用視圖類的OnBegingPrinting()函數(shù),該函數(shù)進一步進行初始化工作,并傳送一個指向設備環(huán)境的指針和一個指向CprintInfo結(jié)構(gòu)的指針。
在開始逐頁打印之前,調(diào)用OnPrepareDC()函數(shù),這是每一頁執(zhí)行一次的打印循環(huán)的開始,該函數(shù)的修改用于顯示或打印文檔的設備環(huán)境,為每頁設置映像模式,創(chuàng)建字體,檢查文檔是否結(jié)束。可以把CPrintInfo結(jié)構(gòu)中的m_bContinuePrinting標志設置為False來發(fā)出打印完畢信號以終止打印作業(yè)。
在調(diào)用了OnPrepareDC()函數(shù)之后,ID_FILE_PRINT消息處理函數(shù)調(diào)用了OnPrint()函數(shù),該函數(shù)的缺省功能是把打印工作放在視圖類的OnDraw()函數(shù)中進行,它傳送一個指向設備環(huán)境的指針和一個指向CprintInfo結(jié)構(gòu)的指針,負責每一頁的打印。
歸納起來,MFC應用程序的打印流程如下:
 圖一、打印流程圖
|
二、文檔分頁打印功能的實現(xiàn) 為了說明如何實現(xiàn)文檔的分頁打印功能,下面給出了分頁打印輸出幾個矩形的實例。首先啟動Visual C++6.0生成一個應用程序框架,并重載視圖類的OnBeginPrinting()函數(shù),在該函數(shù)中獲取設備環(huán)境信息,設置頁高、頁數(shù),由此設置打印對話框的初值,具體代碼如下:
Void CmyView::OnBeginPrinting(CDC*pdc,CprintInfo *pInfo) { CmyDoc *pDoc=GetDocment();//得到文檔指針; ASSERT_VALID(pDoc);//確認指針的有效性; int pageHeitht=pDC->GetDeviceCaps(VERTRES);//由頁頂?shù)巾摰卓纱蛴↑c的個數(shù),從設備環(huán)境中得到頁面高度; int logPixelsy=pDC->GetDeviceCaps(LOGPEXELSY);//每英寸的點數(shù); int rectHeight=(int)(4.2*logPixelsy);//計算矩形的高度,可以由用戶自行設置; int numPages=Pdoc->m_numRects*rectHeight/pageHeight+1;//由矩形數(shù)計算輸出頁數(shù); pInfo->SetMaxPage(numPages);//初始化pInfo結(jié)構(gòu); } |
為了將矩形打印輸出,還應該重載Cview::OnPrepareDC()函數(shù),實現(xiàn)輸出圖形的位置定位,函數(shù)首先測試應用程序是否正在調(diào)用CDC類的成員函數(shù)IsPrinting()打印數(shù)據(jù),若正在打印,則判斷當前頁的數(shù)據(jù)屬于哪一部分,由GetDeviceCaps()函數(shù)得當環(huán)境設備信息;接著確定打印新視圖的原點,并將原點值由SetViewportOrg()傳遞給設備環(huán)境。具體代碼如下:
Void CmyView::OnPrepareDC(CDC*pDC,CprintInfo *pInfo) { if(pDC->IsPrinting())//若正在進行打印則判斷當前頁數(shù)據(jù); { int pageHeight=pDC->GetDeviceCaps(VERTRES); int originY=pageHeight*((pInfo->m_nCurpage-1); pDC->SetViewportOrg(0,-originY) } Cview::OnPrepareDC(pDC,pInfo); } |
三、小結(jié) 通過上文的介紹,相信讀者朋友應該對Visual C++編程實現(xiàn)文檔的分頁打印功能有了一定的了解,大家可以在此基礎上,參考相關(guān)學習資料,根據(jù)應用程序的不同需要,編制實現(xiàn)不同的打印程序。