本文轉載自 星戰紫輝 http://www.cppblog.com/rawdata/archive/2009/02/23/74653.htmlhtml
但C#代碼實現爲本人原創。https://github.com/SnailDev/SnailDev.EmfParser 歡迎star或forkgit
關鍵字: 打印 SPL EMF 文件格式github
Windows的假脫機打印會在Windows\System32\spool\PRINERS目錄下生成.spl和.shd文件,其中的打印內容存貯在.spl文件中,可是.spl文件格式彷佛未公開,那麼如何才能將未知的.spl文件剝離成.emf文件呢?網絡
首先,讓咱們瞭解一下Windows打印機制,這是微軟的官網的一副打印流程圖片:函數
其中ISV是應用軟件接口,IHV是硬件接口,左邊是XP的打印模型,右邊是Vista最新的XPS打印模型,但二者能夠互相轉換,具備良好的兼容性。不過,這裏暫時只關心XP系統的打印過程。線程
網絡打印過程圖:orm
可是這些圖彷佛還不夠詳細,那麼請看下面一副:(摘錄於論文:《基於關鍵字匹配的打印數據截獲系統》):htm
基本的思路是: 打印過程發生時,GDI模塊和打印驅動(由打印機廠商提供)進行基本的數據交換,在假脫機設置環境下,生成打印機命令文件:.spl或.emf文件,做爲一個打印池的做業,而後Windows後臺打印線程處理打印做業,將數據文件送至打印機打印,打印完刪除該打印文件。
好,如今回到正題:.spl文件該如何剝離成.emf呢?看一個例子:
在WinHex中打開一個.spl文件:
blog
參考: http://www.undocprint.org/formats/winspool/spl 中一些打印結構的定義。
首先,.spl文件都是以0x00010000簽名開頭,而後一個DWORD 是emf相關區的文件偏移,第3個DWORD是文檔描述字符串(UNICODE)的文件偏移,第4個DWORD 描述的是端口說明字符串(UNICODE)。大體結構以下:
接口
文件尾就是這個樣子:
當定位到0x50的文件位置,讀取2個DWORD數據以後,就是.emf文件開始了。.emf文件格式是公開的,並且很是簡單,是一系列EMR_XXX開口結構的緊密排列,一般以EMR_HEADER(0x01)開頭,以EMR_EOF(0x0E)結尾。其實咱們根本沒有必要去解析.emf文件格式,Windows SDK有專門顯示.emf文件的API,3個函數就搞定:
HENHMETAFILE hEMF = GetEnhMetaFile("EMF_DumpOK.emf");
PlayEnhMetaFile (dc.m_hDC, hEMF, &rc) ;
DeleteEnhMetaFile (hEMF) ;
而後.spl文件還有一些東西,如今尚未解析出來,可是.emf文件已經剝離出來了,後面的能夠先不理它。
代碼見本人github倉庫 https://github.com/SnailDev/SnailDev.EmfParser