Windows打印體系結構以打印池爲中心,打印機圖形dll的打印接口是打印驅動程序的一部分,打印的流程如下:
- 應用程序通知打印池開始一個新的打印任務;
- 打印池調用打印機接口DLL顯示打印對話框,並將打印設置信息傳給它;
- 應用程序調用GDI進行繪圖操作
- GDI將應用程序的繪圖調用保存在EMF文件中,記錄完畢將之發送給打印池;
- GDI返回應用程序完成一次假脫機打印過程,可以進行其他任務;
- 打印池調用GDI,把EMF文的繪圖命令一條條分解到打印機上下文中;
- GDI通過系統調用,調用GDI引擎實現繪圖操作;
- GDI引擎將GDI繪圖命令分解組合,在打印機圖形DLL的幫助下,完成各種圖形的繪製;
- 打印機圖形DLL將繪圖解碼後的數據發往打印池;
- 打印池把打印機數據發往打印機。
圖1Windows打印流程
實際上開發虛擬打印機過程就是設計第8步的GDI引擎中的圖形繪製命令。
GDI引擎和圖形設備之間的接口叫做 Device driver interface(DDI),DDI函數都有Drv前綴,共有89個,其中GDI引擎和打印機圖形DLL之間的DDI函數可以分成3部分,即初始化函數,文檔和頁面控制函數以及圖形繪製函數(表面鉤子函數)開始打印前要對打印機進行初始化DrvEnableDriver是打印機圖形dll的入口點,相當於一般dll的 dllMain,當GDI引擎加載打印機圖形dll時要先調用這個函數,它負責分配資源和初始化內部變量。
Ecgprint中爲OEMEnableDriver函數,在此函數中鉤入鉤子函數(如 OEMTextout, OEMStartDoc,OEMEndDoc等)DryEnablepdev是很重要的函數,它負責分配驅動程序定義的PDEV(物理設備)結構實例。
其中有兩個結構非常重要:一個是 GDIINFO結構,這個結構設置設備分辨率、物理大小、顏色格式等信息;
另一個是 DEVINFO結構,描述驅動程序圖形能力、缺省字體、設備字體數量和抖動格式等。
Ecgprint中爲 OEMEnablepDev函數,在此函數中沒有設置這兩個結構,不知爲什麼?
DryEnablepdev成功返回後,即表示該打印機設備已初始化,隨後GDI引擎
調用 DrvCompletePDEV來給物理設備準備使用的信號。
在GDI引擎能夠實際開始繪畫之前,必須在 DrvEnableSurface中提供一個繪圖表面。這個表面既可以是GDI引擎管理的位圖表面(用 Eng CreateBitmap創建),即DIB,也可以用 EngCreateDeviceSurface創建設備管理的位圖表面,即DDB。 Ecgprint中沒有實現此函數。
當使用標準DIB時,驅動程序可以讓GDI引擎完成所有的繪製工作而不必鉤入任何函數;否則就要提供自己的實現,除了幾個基本實現的基本鉤子,其他的都可以交給GDI引擎處理。
圖2打印機圖形驅動初始化過程
爲了完成文檔打印,需要實現以下文檔和頁面空直接函數以及表面鉤子函數
表1 需要實現的函數
這個是我在學習打印機驅動開發當中遇到的一個非常不錯的引導性文章,可以很好的有一個大概性的流程認識