VC++中所見即所得打印的簡易實現

  • 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); //轉化座標映射模式  
    		int nScreenWidth = GetSystemMetrics(SM_CXSCREEN); //得到屏幕分辨率的寬和高(我的是1280*1024)  
    		int nScreenHeight = GetSystemMetrics(SM_CYSCREEN);  
    		CSize size = CSize(nScreenWidth, nScreenHeight);  
    		pDC->SetWindowExt(size); //設置視窗大小  
    		int xLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSX);  //得到設備每邏輯英寸的像素數量  
    		int yLogPixPerInch = pDC->GetDeviceCaps(LOGPIXELSY);  
    		float fWidth = (float)xLogPixPerInch / 96 ; //得到電腦屏幕映射到視窗大小比率  
    		float fHeight = (float)yLogPixPerInch / 96; //一般得到的fWidth = fHeight   
      
    		long xExt = (long)(fWidth * size.cx); //得到視窗大小  
    		long yExt = (long)(fHeight * size.cy) ;  
    		pDC->SetViewportExt((int)xExt, (int)yExt); //設置視窗大小(由電腦屏幕映射到視窗大小)  
    	}


       如上所示,首先將座標映射方式改變爲MM_ANISOTROPIC方式,即各向異性的意思,在這種座標方式下,X軸和Y軸的邏輯單位可以進行任意的縮放。改變座標映射方式後,就要確定窗口大小和視口大小,注意窗口大小就是我們在屏幕上所見的尺寸,而視口大小則是實際設備,如打印機等,和顯示器設備每邏輯英寸的象素數量比較所得的比例尺寸。通過函數得到顯示器和打印機每邏輯英寸的象素數量,然後對視口大小進行相應的縮放,就可以使得屏幕上的顯示和打印機的輸出是一致的了。 

       這樣,只通過幾行簡單的代碼,我們就實現了所見即所得的打印。  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章