在VC中所見即所得列印的簡易實現
在VC++6.0中用應用程式嚮導(AppWizard)生成的單文件或多文件程式提供了對列印功能的實現,但遺憾的是如果對自動生成的框架程式不做任何改進,打印出來的文件或圖形和螢幕上的顯示相比就會特別小。為什麼會這樣呢?
本文對這種現象的原因和MFC的列印機制進行了深入的分析,並提出了一種特別簡單的方法,在原有的程式中只需加入幾行程式碼就能解決這一問題,實現所見即所得的列印。
首先,分析MFC的列印機制,把原理弄清楚了,就不難明白現象形成的原因和提出解決辦法。MFC應用程式的核心是文件物件以及相關的檢視視窗的概念,即CDocument類和CView類的構成和關係,簡單地說CDocument類負責資料的生成和儲存,CView類負責資料的顯示和使用者互動。輸出到螢幕和輸出到印表機都是資料的顯示,實質上是一樣的,所以列印功能也是由CView類來實現的。
在CView類中由應用程式嚮導自動生成的原始碼提供了一個OnDraw(CDC* pDC)的函式,通過過載這個函式,利用它提供的pDC(裝置上下文)指標,可以在螢幕上顯示各種圖形和資料。CView類的列印是通過OnPrint(CDC* pDC, CPrintInfo* pInfo)這個函式實現的,應用程式嚮導自動生成的原始碼中沒有這個函式的框架,而這個函式對列印的實現就是簡單地呼叫OnDraw(CDC* pDC)這個函式,把印表機的裝置上下文指標pDC傳遞給OnDraw(CDC* pDC)函式。
可見CView類對輸出到螢幕和輸出到印表機的處理都是一樣的,只是換了一個裝置上下文而已,那麼為什麼輸出到印表機的影象特別小呢?
這與VC採用的預設的座標對映方式MM_TEXT有關,這種方式的好處是使用者圖形座標和裝置的象素完全一致。但是在螢幕的象素大小為800*600時,每邏輯英寸包含的螢幕象素為96,而印表機的點數卻要多好幾倍,如當印表機為HP LaserJet 6L時每邏輯英寸包含的印表機點數為600,也就是說印表機的清晰度比螢幕要高得多。
這樣的後果就是在螢幕上顯示出來的滿屏影象在打印出來的紙上卻只有一點點大,怎麼解決這個問題呢?一種簡單的方法就是轉換座標對映方式,使得列印時採用的座標比例比顯示時採用的座標比例相應地大若干倍,就可以解決這一問題。
下面將給出詳細的方法。
注意到CView類在進行顯示和列印之前都會呼叫virtual void OnPrepareDC( CDC* pDC, CPrintInfo* pInfo = NULL )這個虛擬成員函式來準備裝置上下文,我們可以在CView類中過載這個虛擬成員函式,進行座標轉換。
首先用VC的ClassWizard實現對OnPrepareDC( CDC* pDC, CPrintInfo* pInfo = NULL )函式的過載,ClassWizard生成的原始碼如下:
void CTempView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{ // TODO: Add your specialized code here and /or call the base class
CView::OnPrepareDC(pDC, pInfo);
}
我們只需在原始碼中加入以下幾行程式碼即可,如下:
void CPrintSameView::OnPrepareDC
(CDC* pDC, CPrintInfo* pInfo)
{ CView::OnPrepareDC(pDC, pInfo);
pDC->SetMapMode(MM_ANISOTROPIC); //轉換座標對映方式
CSize size = CSize(800, 560);
pDC->SetWindowExt(size);
//確定視窗大小 //得到實際裝置每邏輯英寸的象素數量 int xLogPixPerInch = pDC->
GetDeviceCaps(LOGPIXELSX);
int yLogPixPerInch = pDC- >GetDeviceCaps(LOGPIXELSY);
//得到裝置座標和邏輯座標的比例 long xExt = (long)size.cx * xLogPixPerInch/96 ;
long yExt = (long)size.cy * yLogPixPerInch/96 ;
pDC->SetViewportExt((int)xExt, (int)yExt);
//確定視口大小 }
如上所示,首先將座標對映方式改變為MM_ANISOTROPIC方式,即各向異性的意思,在這種座標方式下,X軸和Y軸的邏輯單位可以進行任意的縮放。改變座標對映方式後,就要確定視窗大小和視口大小,注意視窗大小就是我們在螢幕上所見的尺寸,而視口大小則是實際裝置,如印表機等,和顯示器裝置每邏輯英寸的象素數量比較所得的比例尺寸。通過函式得到顯示器和印表機每邏輯英寸的象素數量,然後對視口大小進行相應的縮放,就可以使得螢幕上的顯示和印表機的輸出是一致的了。
這樣,只通過幾行簡單的程式碼,我們就實現了所見即所得的列印。