讓低版本的office支持將文檔打印成圖片的工具,ImagePrinter可以將文檔“打。ㄌ摂M打。背葿MP、PNG、JPG、PDF等格式的文件,安裝后會(huì)成為系統(tǒng)的默認(rèn)打印機(jī)!窱magePrinter」的體積只有900多KB
安裝時(shí)問你是否安裝驅(qū)動(dòng)程序,選擇“是”
虛擬打印機(jī)有三種定制方法:
1、驅(qū)動(dòng)層(Driver)一種。好像是修改Render plug-in什么的。沒做過。
2、打印假脫機(jī)(splooer)層兩種。
(1)自定義打印處理器(PrintProcessor),一般是修改DDK中g(shù)enprint的例子。將自定義的代碼加入到PrintDocumentOnPrintProcessor中。
(2)在監(jiān)視(Monitor)層。
打印假脫機(jī)(splooer)層兩種的兩種實(shí)現(xiàn)方法驅(qū)動(dòng)層一般都用微軟統(tǒng)一驅(qū)動(dòng)程序(UniDrv)。
通過打印測試頁可以了解安裝的打印驅(qū)動(dòng)的各個(gè)方面:驅(qū)動(dòng)程序、端口等。也可以通過打印機(jī)的屬性查看。
ImagePrinter是用的自定義端口的形式實(shí)現(xiàn)虛擬打印。
虛擬打印機(jī)驅(qū)動(dòng)ImagePrinter的開發(fā):
ImagePrinter是在Port監(jiān)視器端的虛擬打印機(jī)。
(1)在系統(tǒng)開機(jī)時(shí),順序調(diào)用以下函數(shù):DllMain--->InitializePrintMonitor--->iEnumPorts(2次,后一次參數(shù)都是NULL)--->iOpenPort;
(2)在打印文檔時(shí),順序調(diào)用以下函數(shù):iStartDocPort--->iWritePort(很多次)--->iEndDocPort。
以下是DDK的翻譯(根據(jù)對(duì)代碼的理解,有刪減):
(1)初始化打印監(jiān)視器
當(dāng)spooler調(diào)用LoadLibrary來加載的打印監(jiān)視器DLL,系統(tǒng)立即調(diào)用DLL的DllEntryPoint函數(shù)。可以在此時(shí)LisableThreadLibraryCalls,這樣創(chuàng)建和刪除線程時(shí),不必非得這個(gè)通知DLL。
每一個(gè)DLL都導(dǎo)出一個(gè)初始化函數(shù),可以供spooler在調(diào)用LoadLibrary后調(diào)用。Language monitor DLL和port monitor server DLL導(dǎo)出InitializePrintMonitor2函數(shù)。port monitor UI DLL的導(dǎo)出InitializePrintMonitorUI函數(shù)。(總共有3中Monitor)。
這兩個(gè)初始化函數(shù)的作用是返回其他函數(shù)(EnumPorts,OpenPort,StartDocPort等所有以下用的函數(shù))的指針,這樣spooler就可以調(diào)用它們了。初始化函數(shù)也可以執(zhí)行l(wèi)oad time的初始化操作。
InitializePrintMonitor2函數(shù)返回一個(gè)監(jiān)視器實(shí)例句柄。monitor應(yīng)分配本地內(nèi)存來存儲(chǔ)自定義的一些信息,并以此句柄為標(biāo)識(shí)來分配內(nèi)存。
當(dāng)spooler第一次啟動(dòng)時(shí)(一般是開機(jī)時(shí),如果你開機(jī)啟動(dòng)了spooler服務(wù)的話),它會(huì)載入所有已安裝的monitor DLL的。所有Monitor的初始化函數(shù)調(diào)用后,打印后臺(tái)處理程序調(diào)用每個(gè)port monitor的EnumPorts函數(shù),其中列舉了monitor支持的端口。monitor支持一個(gè)端口,如果端口已被添加到monitor的數(shù)據(jù)庫。然后打開每個(gè)支持的端口。
(2)打開和關(guān)閉端口
spooler 通過調(diào)用language monitor的OpenPortEx函數(shù)打開端口;相對(duì)應(yīng)的Port monitor調(diào)用OpenPort函數(shù),language monitor只返回從Port monitor的OpenPort獲得的句柄。如果沒有l(wèi)anguage monitor,就直接調(diào)Port monitor的OpenPort函數(shù)。打開一個(gè)端口后不關(guān)閉的話,不能再打開。
端口一經(jīng)打開,打印后臺(tái)處理程序就可以調(diào)用其他函數(shù)來打印作業(yè)了。這些函數(shù)使用OpenPort返回的句柄作為輸入。什么時(shí)候端口關(guān)閉呢:系統(tǒng)關(guān)機(jī),沒打印任務(wù)....
(3)打印打印作業(yè)
每個(gè)打印作業(yè)以StartDocPort開始,以EndDocPort結(jié)束。當(dāng)print processor 調(diào)用的spooler的StartDocPrinter EndDocPrinter的函數(shù)時(shí),這兩個(gè)函數(shù)被調(diào)用。在這兩個(gè)函數(shù)調(diào)用中間,不定量的WritePort, ReadPort, and GetPrinterDataFromPort函數(shù)被調(diào)用。
這些函數(shù)都需要用到OpenPortEx(或OpenPort)返回的句柄( port handle)作為輸入?yún)?shù)。
當(dāng)spooler調(diào)用language monitor 的WritePort函數(shù),以將數(shù)據(jù)流發(fā)送到端口時(shí),這些函數(shù)一般只增加一些特定的語言信息到接收到的數(shù)據(jù)流上,如PJL命令然后將它傳遞給相關(guān)的port monitor的WritePort功能。
ReadPort函數(shù)是用于獲取雙向打印機(jī)硬件的狀態(tài)信息。Language monitor 通過調(diào)用SetPort將信息發(fā)送到spooler,獲得狀態(tài)信息。spooler不能調(diào)用ReadPort的函數(shù)。
如果打印硬件是雙向的,language monitor和port monitor 都應(yīng)該實(shí)現(xiàn)GetPrinterDataFromPort函數(shù)。language monitor的GetPrinterDataFromPort函數(shù)以注冊(cè)表值的名稱為輸入,獲得該名稱的值(通常由調(diào)用相關(guān)的端口監(jiān)視器的WritePort和ReadPort功能),并返回值給調(diào)用者。port monitor 的GetPrinterDataFromPort函數(shù)應(yīng)該接受一個(gè)I / O控制代碼作為輸入,調(diào)用DeviceIoControl返回控制代碼給port driver,并返回結(jié)果。