打印操作的后台原理
Windows的所有绘图指令,都集中在GDI模块中,称为GDI绘图函数。
图形输出到何处。关键是DC,这是任何GDI绘图函数的第一个参数,可以是GetDC或BeginPaint函数所获得的”显示器DC”.
每一个送往打印机DC的秽土操作,其实都只被记录为metafile,存储在我们的TEMP目录中。当调用Escape(hPr,NEWFRAME,…)时,打印机驱动程序(。DRV)会把这些metafile转换为打印语言(control Sequence或Postscript).然后通过GDI模块,由GDI把它存储为.SPL文件,也放在TEMP目录下,并删除对应的metafile。之后,GDI模块再送出消息给打印管理器Print Manager,由后者调用OpenComm,WriteComm等底层通讯函数(也都是Windows API函数),把打印机命令传递给打印机。
Metafile是一种图形记录规格,但它记录的是绘图操作,不象bitmap记录的是真正的图形数据。所以播放metafile比播放bitmap慢。因为多了一层绘图函数解读操作;但它的大小比bitmap小很多,用在许多矩形,圆形,工程几何图形上最为方便。
Windows程序
↓
取得打印机DC,于是载入打印机驱动程序(DRV)
↓
Escape(hpr,STARTDOC,…),于是DRV初始化并载入Print Manager
↓
各式各样的GDI绘图函数(存储为metafile,~MF文件) <---------------------|
↓ |
Escape( hpr , NEWFRAME ,… ) |
↓ |
DRV解读metafile转换为control sequence或Postscript,传给GDI |
↓ |
GDI把DRV的输出存储在~SPL暂存文件中,并删除~MF文件 |
↓ |
GDI送消息给Printer Manager,要求打印机输出,应用程序继续进行自己的动作--|
↓
Print Manager读~SPL文件,利用OpenComm,WriteComm等
API函数把资料(打印机)送往打印机,完毕后删除~SPL文件
MFC默认的打印机制
Windows的图形装置接口(GDI)完全与硬件无关,相同的绘图操作如果送到“显示器DC”,就是在屏幕上绘图;如果送到”打印机DC”,就是在打印机上绘图。
MFC应用程序中,View和Application framework分工合力完成打印工作。
Application framework的责任是:
#显示print对话框
#为打印机产生一个CDC对象
#调用CDC对象的StartDoc和EndDoc两个函数
持续不断地调用CDC对象的StartPage,通知View应该输出哪一页;一页打印完毕则调用CDC对象的EndPage.
View对象上的责任是:
#通知Application framework总共有多少页要打印。
#Application framework要求打印某特定页时,我们必须将Document中对应的部分输出到打印机上。
#配置或释放任何GDI资源,包括笔,刷,字形等等。
#若需要,则送出任何escape代码改变打印机状态,例如走纸,改变打印方向等。送出escape代码的方式是调用CDC对象的Escape函数。
配置GDI绘图工具
绘图难免需要各式各样的画笔,画刷,颜色,字形,工具。这些GDI资源都会占用内存,而且是GDI模块的heap.我们当然不希望浪费资源,因此最好的方式是在打印之前配置这些GDI绘图对象,并在打印后立即释放。
配置GDI对象的最理想时机显然是OnBeginPrinting,有两个理由:
1每当Framework开始一份新的打印工作时,它就会调用此函数一次,因此不同的打印工作所需要的不同工具可在此有个替换。
2 此函数的参数是一个和”打印机DC”有附着关系的CDC对象指针,我们直接从此一CDC对象中配置绘图工具即可。
释放GDI对象的最理想时机当然是在OnEndPrinting,这是每当一份打印工作结束后,Application Framework会调用的函