《打印程序开发资料.docx》由会员分享,可在线阅读,更多相关《打印程序开发资料.docx(28页珍藏版)》请在三一办公上搜索。
1、基于组件模型的虚拟打印系统的研究与实现虚拟打印是利用某种方式截获操作系统的打印任务,将打印任务转换为图像文件并保存在指定目录的系统。 通过虚拟打印系统,用户可以将任意可打印的文档转换为统一的图像文件,由一种应用程序进行浏览。因 此在Web环境、多客户端情况下,客户端不需要为浏览多种应用程序的文件而安装多种应用程序,便于实 现瘦客户端和降低系统的软件成本。本文通过研究比较现有的虚拟打印系统,提出建立基于组件模型的虚 拟打印系统,主要介绍的技术包括:虚拟打印机的实现、虚拟打印机的安装卸载、系统二次开发接口等。1 Windows打印系统结构虚拟打印基于Windows打印体系,是对Windows打印系
2、统的一种应用及拓展。微软的Windows NT系列 打印体系结构由打印假脱机和一套打印驱动程序组成。应用程序对Win32 GDI函数的调用传送到GDI图形引擎,GDI图形引擎可以将绘制指令假脱到一个EMF 文件中,或者与打印驱动程序连接,向假脱机绘制一个可打印的图像。假脱机组件解释EMF文件,他们可 以在数据流中插入页面布局信息以及作业控制指令。然后假脱机将数据流发送给具有目标打印机I/O端口 的串行、并行或网络端口的驱动程序。其体系结构如图1所示。2虚拟打印系统的研究按照获取打印任务方式的不同,可以将虚拟打印系统分为3种类型:重写Print Processor,在假托模块中 实现转换,例如M
3、abuse.De的VPrinter;采用回调机制在打印任务发送到Spoolez之前获取打印数据流, 例如NortheastData公司的Image Printer Driver;通过监视Port Monitor获取打印任务数据,例如Adobe 公司的 Adobe AcrobatWriter。目前绝大部分虚拟打印系统都是独立的系统,使用各自的文件格式来保存打印结果,很少以组件的方式提 供二次开发接口,使得上述虚拟打印系统很难与其他应用系统进行集成。本文研发的基于组件模型的虚拟 打印系统,采用重写Print Processor方式实现打印任务的获取。该系统提供了丰富的二次开发接口,可以 按照应用系
4、统集成商的要求提供文档转换功能,最大限度地降低了应用系统的成本。3虚拟打印系统的实现基于组件模型的虚拟打印系统主要包括2部分:打印机驱动程序模块和二次开发接口模块。其体系结构如图2所示:打印任务的截取,是整个虚拟打印系统的关键部分。从图1中可以看出,Print Processor负责将打印任务处理后发送到Port Monitor,Print Processor是一个可替换的DLL,安装DDK中的约定,实现以下6个函 数,就可以自定义一个Print Processoro(1)EnumPrintProcessorDatatypes,该函数主要处理并返回打印处理器所能处理的数据类型;ControlP
5、rintProcessor,该函数主要提供方法供用户控制打印处理器,如停止、删除、重新开始打印任 务等;(3)GetPrintProcessorCapabilities,该函数主要供Windows系统获取针对某种输入数据的处理能力;OpenPrintProcessor,返回该打印处理器的句柄给系统;PrintDocumentOnPrintProcessor,处理打印任务,将处理后的数据发送到Port Monitor或者转换为图 像文件等;(6)ClosePrintProcessor,关闭打印处理器。图3详细说明在PrintDocumentOnPrintProcessor中如何将打印任务转换为图
6、像文件的过程。3.2生成指定格式、大小的图像虚拟打印系统获取的打印页面原始数据是EMF矢量图形文件。如果转换前的文档中没有大量的图片信息, 那么转换后的EMF文件是比较小的,一般1页Word转换后在2050 k大小。因此本系统提供了配置接 口供用户选择最终保存的图像格式,目前支持JPG,GIF,PNG等常用的图像格式。可以按照如下方式修 改图像的格式和大小:ImageInfoImageWidth=1024ImageHeight=768ImageType=JPG以上信息设定后,转换生成的图片为JPG格式文件,图片宽为1 024 pixel,高为768 pixel。3.3封装组件,提供二次开发接口
7、二次开发接口是虚拟打印系统提供给第三方应用系统调用或设置的方法。良好丰富的二次开发接口,使得 本系统可以快速便捷的与第三方应用系统进行集成,大大提高系统的应用范围。按照组件模型的思想,本 系统中将二次开发接口封装成ActiveX组件,使得用户可以通过简单的JavaScript调用接口方法。3.3.1安装、卸载打印机接口一般采用由最终用户通过在控制面板中选择添加打印机的方式来安装打印机。这种方法对最终用户要求比 较高,不适合大规模的应用。因此,封装了一个Acitvex实现打印机的安装和卸载,使得第三方应用系统 可以非常方便地安装、卸载虚拟打印机。该ActiveX提供以下2个方法:(l)Insta
8、llVirtualPrint,实现安装打印机,关键部分解释如下:hoc n奖:DRIVEK_INFO_3 Driwcrfnfoai揣加打印甥动茬序JUg= AddRri n inrOri vcr( NUI .3- t & rrLvrl ) ie * *!=*?-Fif CUprnf rinrerVFrinter i. &hp &pd)1 制除JJ印包if (nl3e= DeleccPntiterChp)l 如梁失败,返回出锚代码rcium GeH.asrErrorO i J )3.3.2打印机信息设置接口为了方便第三方系统集成,打印机基本信息存储在系统INI文件中。集成用户按照标准可以非常方便
9、地修 改打印机的相关信息,例如:转换后图像文件的保存路径,当前文件的前缀等。EFblelnfoDiretcufj =寸白1网PrefsK 123 以上信息设定后,转换生成的图像文件就保存在c:123目录下,文件名称按以下规则形成“123_页码”。 第三方系统也可以通过编程的方式动态修改配置文件。3.3.3图像生成事件通知接口在第三方系统集成时,希望实时知道什么时候转换完成,什么时候转换了某一页。因此本系统采用Windows 广播消息的方式来通知集成系统。广播消息是Windows系统中,不同进程之间通信最实时、最快捷的方式。广播消息分为2个步骤:利用RegisterWindowMessage函数
10、向Windows系统注册消息句柄;利用PostMessage函数寄送消息,需要注意的是第一个参数必须为HWND_BROAD-CAST。集成系统可以在 消息循环中获取广播的消息,以VC开发工具为例,如下过程就可以获取广播的消息:利用RegisterWindowMessage注册同一消息句柄;利用ON_REGISTERED_MESSAGE宏,映射消息句柄到 消息处理函数。4结语在研究现有虚拟打印系统的基础上,指出这些系统存在的问题,研究并实现基于组件模型的虚拟打印系统。 该系统具有转换快速、二次开发接口丰富等特点,并且巳经应用在第三方系统中,如:iWebOffice网络文档、iSignatureG
11、DF电子签章系统。定制打印假脱机组件本章解释怎样定制打印机假脱机组件,并提供了以下这些主题:编写打印处理器编写打印监示器编写网络打印提供者8.1编写打印处理器本部分提供下面的主题: 8.1.1对打印处理器的介绍 8.1.2打印处理器示例 8.1.3由打印处理器定义的函数 8.1.4处理一个打印作业 8.1.5安装一个打印处理器8.1.1对打印处理器的介绍打印处理器是用户模式的一些DLL,主要负责转换打印作业的假脱数据到打印机 监示器的格式。也负责处理应用程序对暂停、重新开始及撤消打印作业等的请求。打印作业的假脱数据包含在一个假脱文件中。打印处理器读取这些文件,在数据 流上执行转换操作,并将转换
12、的数据写到假脱机。假脱机然后发送数据流到合适 的打印机监示器。微软Windows 2000包括列在下表中的打印处理器。打印处理器 输入数据类型 输出数据类型winprint.dllEMFRAWTEXTRAWstmpsprt.dllPSCRIPT1RAW关于数据类型的信息,参考下面的主题: EMF数据类型 RAW数据类型 TEXT数据类型 PSCRIPT1数据类型可以创建一个定制的打印处理器以支持一个Windows 2000不支持的数据类型。 也可以提供一个定制的打印处理器以支持一种或更多种的被支持的数据类型,这 样,就允许修改由打印处理器所提供的能力。打印处理器与在打印机驱动程序安装时与打印机
13、的驱动程序相关,因此,可以并 存多个打印处理器支持同一种数据类型。更多的信息,参考安装打印机处理器部 分的内容。EMF数据类型增强型元文件(EMF:Enhanced Metafile)数据类型由调用GDI函数的指令构成。 打印处理器必须调用GDI函数以绘制可打印的图像。GDI函数对打印驱动程序的 打印机图形DLL做调用,它绘制图像并将它作为RAW数据向假脱机发送(通过调 用 EngWritePrinter)。Windows NT/Windows 2000 客户端发送 EMF 数据到 Windows NT/Windows 2000 打印服务器。EMF数据是设备独立并可以比RAW数据类型更快速地发
14、送到服务器。 当一个应用程序请求是从本地到服务器,打印作业也就被假脱处理为EMF数据, 这样就允许在作业被后台假脱机绘制时能够对应用程序的快速返回。更多的关于EMF数据类型的信息,参考Windows 2000专业版资源包(Windows 2000 Professional Resource Kit)或 Windows 2000 服务器版的资源包(Windows 2000 Server Resource Kit)。更多的关于增强型元文件的信息,参考平台SDK文档。RAW数据类型RAW数据可以不用进一步处理就被发送到打印机监示器。打印机处理器只发送这 一数据到假脱机(通过调用WritePrinte
15、r,在平台的SDK文档中描述),有时插 入表格。一个RAW数据文件的实例是一个由PCL命令组成的。无论客户端或服务 器端那一方不支持Windows NT/Windows 2000 EMF或者服务器管理员禁止了 EMF 支持,打印作业以RAW数据格式从客户端发送到服务器端。在这些情况下,客户 端的图像绘制在打印作业发送到服务器端之前进行。(Postscript命令可以被当作RAW数据,如果目标打印机支持Postscript。另一 方面,stmpsprt.dll打印处理器将Postscript的输入向非Postscript的打印 机进行解释,在这种情况下,Postscript不是RAW数据。)更多
16、的关于RAW数据类型的信息,参考Windows NT工作站资源指南或者Windows NT资源指南部分的内容。TEXT数据类型 单纯由ANSI文本构成的。打印机处理器调用GDI以用打印机设备容错字体绘制 字母,并发送RAW格式的结果输出到假脱机(通过调用Writeprinter,在平台的 SDK文档中描述)。处理器等同于用写字板打开输入文件并然后打印文件(该格式 用于不能打印文本字符的打印机)。更多的关于TEXT数据类型的信息,参考Windows NT工作站资源指南或者Windows NT服务器资源指南部分的内容。PSCRIPT1数据类型PSCRIPT1数据的目的是要在一个非Postscrip
17、t打印机上打印的Postscript数 据。打印处理器解释Postscript命令并且向输出文件写RAW格式的结果数据。更多的关于PSCRIPT1数据类型的信息,参考参考Windows NT工作站资源指南或 者Windows NT服务器资源指南部分的内容。8.1.2打印处理器示例genprint.dll的源代码,一个接受EMF数据、RAW数据及TEXT数据作为输入的 打印处理器的实例,包含于本DDK中。其代码位于DDK实例的目录树中的 genprint的子目录中。8.1.3由打印处理器定义的函数打印机处理器必须导出下表列出的函数:函数名称描述ClosePrintProcessor关闭打印处理器
18、ControlPrintProcessor提供对打印文档的控制EnumPrintProcessorDatatypes 枚举打印机处理器支持的数据类型GetPrintProcessorCapabilities为专用的输入数据类型返回打印处理器的能力OpenPrintProcessor为打印打开打印处理器PrintDocumentOnPrintProcessor在一个打印处理器上打印文档8.1.4处理一个打印作业当一个假脱机准备发送一个打印作业到打印处理器时,它调用打印处理器的 OpenPrintProcessor函数。这一函数执行初始化活动并返回一个句柄。假脱机可以调用PrintDocument
19、OnPrintProcessor,它是打印处理器的一个函数, 可以从输入格式到输出格式转换数据流,并返回被转换的流到假脱机。如果输入的格式是Windows NT/Windows 2000的EMF,则 PrintDocumentOnPrintProcessor函数将通过使用GDI的打印处理器函数来控制 EMF记录的回放。这些函数提供了一个打印处理器与打印机驱动程序之间的接口。 该接口允许打印处理器控制打印机页面的物理布局及实现诸如在一个物理页面 上打印多个文档页面(“N-up”打印)、反向打印、每页打印多个拷贝等等。一个打印处理器的输出数据流必须返回到假脱机。通常,如果数据转换需要与打 印机驱动
20、程序的打印机图形DLL(对EMF格式作为输入数据时)之间交互作用,则 图形DLL通过调用EngWritePrinter。另外一方面,如果转换不调用打印机图形 DLL(当输入数据是RAW类型时),则打印处理器调用WritePrinter(在平台的SDK 文档中描述)。PrintDocumentOnPrintProcessor函数可以从假脱机到打印处理器的 ControlPrintProcessor函数同步调用中断。这一函数实现应用程序的暂停、恢 复及撤消一个打印作业等能力。在PrintDocumentOnPrintProcessor结束转换数据流并返回后,假脱机调用打印 机处理器的ClosePr
21、intProcessor函数。8.1.4.1为打印处理器使用GDI函数一套用户模式的GDI函数被gdi32.dll导出,对被打印处理器用于处理WindowsNT/Windows 2000的EMF作为输入格式。下面的表列出了可以提供的函数:函数名称描述GdiDeleteSpoolFileHandle释放一个假脱机文件句柄GdiEndDocEMF对一个打印文档完成EMF回放操作GdiEndPageEMF为一个物理页面完成EMF回放操作,并从打印机跳页GdiGetDC返回一个打印机设备设备环境的句柄GdiGetDevmodeForPage返回一个文档页面的DEVMODE结构GdiGetPageCou
22、nt返回文档页面的数字GdiGetPageHandle返回文档页面的句柄GdiGetSpoolFileHandle返回一个假脱文件的句柄,它对其他的GDI函数是作为一个必需的输入GdiPlaypageEMF播放与文档页面相关的EMF记录GdiResetDCEMF重置打印机的设备设备环境GdiStartDocEMF对打印作业执行初始化操作GdiStartPageEMF对物理页面执行初始化操作 一个EMF打印处理器的PrintDocumentOnPrintProcessor应当调用GdiGetSpoolFileHandle以获得假脱文件的句柄及调用GdiGetDC以获得打印机 设备设备环境句柄。然
23、后它可以执行下面的操作: 对每一个打印作业文档,GdiStartDocEMF必须在任何EMF记录被运行之前调 用并且GdiEndDocEMFnt必须在EMF记录运行完之后被调用。对每一个要被打印的物理页面来说,GdiStartPageEMF必须在任何文档页面在 页面上被绘制之前被调用,GdiEndPageEMF必须在最后一个文档页面被在物理页 面上绘制完之后被调用对每一个将要绘制在物理页上的文档页面来说,GdiGetDevmodeForPage是否 必须被调用取决于DEVMODE结构的内容是否在最后一个文档页被绘制之后改变。 如果DEVMODE已经改变,一个新的物理页而必须开始(通过调用Gdi
24、EndPageEMF 及GdiStartPageEMF),打印机的设备设备环境必须通过调用GdiResetDCEMF来 改变。一个文档页面必须被绘制在物理页面上,通过首先调用GdiGetPageHandle 以获得文档页面句柄,并然后调用GdiPlayPageEMF以绘制页面。在打印作业已经完成绘制后,打印处理器必须调用GdiDeleteSpoolFileHandle。如果一个打印处理器在它开始打印页面之前需要知道总的打印页数(如反向打印 时),它可以调用GdiGetPageCount,但是这一函数将一直到假脱过程完成并且 在假脱时禁止了打印能力时才返回。如果一个打印处理器用这些GDI函数,它
25、的EnumPrintProcessorDataTypes函数 必须返回“NT EMF”作为一个支持的数据类型,它表示一般的Windows 2000 EMF 格式。打印处理器不能修改EMF记录。8.1.5安装一个打印处理器为安装一个打印处理器,一个安装应用程序必须调用假脱机的 AddPrintProcessor函数,它在平台的SDK文档中描述。为关联一个打印机处理器与一个打印机驱动程序,它的文件名称必须通过使用 PintProcessor条目而被列在.inf文件中。这一条目必须为每一个将要被与打印 处理器关联的打印机驱动程序所包含。更多的信息,可以参考第10章的打印机 INF文件部分的内容。当一
26、个安装应用程序调用假脱机的AddPrinter函数,指定一个PRINTER_INFO_2 结构作为一个输入参数,它指定打印机处理器名称(从.inf文件获得)作为一个 结构成员。(AddPrinter函数及PRINTER_INFO_2结构在平台的SDK文档中描述)。8.2编写打印监示器打印监示器负责传送打印机数据流从打印假脱机到一个合适的端口驱动程序。两 种类型的打印机监示器被定义,即 语言监示器(language monitors)及端口 监示器(port monitors)。这一章将描述两种监示器,并提供设计与实现的指南。提供以下内容的主题: 8.2.1语言监示器 8.2.2端口监示器 8.
27、2.3语言和端口监示器交互 8.2.4由打印监示器定义的函数 8.2.5初始化一个打印监示器 8.2.6打开及关闭一个端口 8.2.7打印一个打印作业 8.2.8管理端口 8.2.9为在集群打印服务器中使用转换打印监示器 8.2.10安装打印监示器8.2.1语言监示器语言监示器是一些用户模式的DLL,主要用于两个目的:它们在打印机假脱机与双向打印机之间提供了一个全双工的通信通道,从而具 有了提供软件可存取的状态信息的能力。增加打印机控制信息到数据流,如由打印机作业语言定义的命令等。微软提供了一个语言监示器pjlmon.dll,它支持打印作业语言(PJL:Printer Job Language
28、),并为PJL打印机提供双向通讯。这一监示器被作为语言监示器示例 包含在这一 DDK中。对单向或双向打印机来说,定制的语言监示器可编写用于支持其他作业控制语言。语言监示器是可选的,并且只与特殊的包含在打印机的.inf中的打印机类型相 关,如在安装打印监示器部分所描述的。如果一个语言监示器与打印机关联,语言监示器从打印机处理器收到打印机的数 据流,修改它并将之传递到打印机的端口端示器。更多的信息,可参考语言监示 器及端口监视器交互部分的内容。8.2.1.1语言监示器示例pjlmon.dll的源代码,支持双向PJL语言的语言监示器就包括在这一 DDK中。 其代码位于DDK的实例目录树中的pjlmo
29、n子目录中。8.2.2端口监示器端口监示器由用户模式的一些DLL组成。它们负责在用户模式的打印假脱机及访 问I/O硬件端口的内核模式的端口驱动程序之间提供通讯。一个端口监示器通常 使用 CreateFile,WriteFile,ReadFile 及 DeviceIOControl 函数,在平台的 SDK文档中描述的,以与内核模式的端口驱动程序通讯。端口监示器也负责管理 及配置一个服务器的打印机端口,如在管理端口部分所描述的。Windows NT/Windows 2000用户的“打印机”视图实际上是一个打印队列,是一 个或多个物理打印机设备都可以连接到的队列。一个端口是一个在打印队列及一 个单一
30、打印机设备之间的物理连接。每一个端口端示器支持一个或多个的一种 或多种端口类型的实例。例如,localmon.dll这一示例的端口监示器可以支持 所有的服务器的本地COM及LTP端口。(打印机文件夹)通过调用平台SDK文档中 描述的AddPrinter函数来分配端口到端口监视器)。对表示多个打印机设备(通过多个端口)的打印机队列来说,假脱机发送每个打印 作业到第一个可用的端口。如果端口监示器指明一个可用端口忙或者遇到错误, 假脱机将重新提交作业到队列,指定另外一个端口监示器支持的可用端口。除了 localmon.dll, Windows 2000提供几个附加的端口监示器。Windows NT服
31、 务器资源开发包中对每一个这样的端口监示器都做了描述。可以写定制的端口监示器以支持附加类型的硬件I/O端口。对Windows 2000来说,每一个端口监示器被分为两个DLL。端口监示器UI DLL端口监示器的用户接口 DLL包含用户接口的功能并在打印客户系统上执行。这一 DLL必须驻留在客户系统的System32子目录中。端口监示服务器DLL一个端口监示器的服务器DLL包含端口通讯功能及在打印服务器上执行。它必须 显示一个用户的接口。UI DLL通过调用假脱机的Xcvdata函数与服务器的DLL通讯,在该DDK中包含 一个端口监示器实例。8.2.2.1端口监示器实例localmonn.dll的
32、源代码,即支持本地LPT及COM端口的端口监示器也在DDK中 包含着。其代码位于DDK实例目录树的localmon及localui子目录中。8.2.3语言和端口监示器交互下面的图显示了打印机数据从打印处理器到打印机的路径图。其中图(a)包含一 个与它相关联的语言监示器,图(b)不包含相关联的语言监示器。插入图(a)(b)?如果一个语言监示器在打印机的安装过程中与打印机关联,语言监示器从假脱机 打印处理器中收到打印机的数据流。语言监示器修改数据流并将它传递到打印机的监示器。许多由打印机定义的监示器对语言监示器及端口监示器是相同的。通常,如果一 个语言监示器在数据流通道中,假脱机将调用端口监示器的
33、实现函数而语言监示 器将调用端口监示器的同样的实现函数。例如,在PJL语言监示器(pjlmon.dll) 中的WritePort函数增加PJL命令到数据流然后调用端口监示器的WritePort 并将该流发送给端口驱动程序。如果没有安装语言监示器,假脱机调用端口监示器的函数实现。由于语言监示器及端口监示器是打印体系中分散的组件,定制的及微软提供的监 示器可以被一起应用。这样,可以提供一个与微软提供的端口监示器一起工作的 定制的语言监示器,反之亦然。也可以提供一个单一的语言和端口监示器构成(combined language and port monitor)的组合式打印监示器。8.2.3.1组合
34、式语言和端口监示器专用的打印机硬件可以被一个单一的定制打印监示器支持,它实际作为一个组合 式的语言和端口监示器。如果这样一个监示器需要用户的交互以获得配置参数, 它必须被分成UI DLL及一个服务器的DLL,下面的模型是对端口监示器的。而 语言相关的功能则属于服务器DLL。一个组合的监示器UI DLL必须定义端口监示器客户端DLL函数。它的服务器DLL 必须定义端口监示器服务器DLL的函数及语言监示器的函数。8.2.4由打印监示器定义的函数下面的部分列出了在打印监示器中必须定义的函数: 8.2.4. 1语言监示器函数 8.2.4.2端口监示器客户DLL函数 8.2.4.3端口监示器服务器DLL
35、函数8.2.4.1语言监示器函数下表列出了语言监示器必须定义的函数: 函数名称描述DllEntryPointDLL入口点,通常称为DLLMain,它在平台的SDK文档中描述ClosePort关闭一个端口,在没有打印机与它相连时EndDocPort在一个端口上执行打印作业完成的任务GetPrinterDataFromPort(可选)轮询存储在注册表中的端口值InitializePrintMonitor2初始化打印监示器并返回一个实例句柄OpenPortEx为一个新连接的打印机打开一个端口ReadPort从一个打印机端口读数据StartDocPort执行在一个端口上开始打印作业的操作WritePo
36、rt向打印机端口写数据8.2.4.2端口监示器客户DLL函数下面的表格列出了一个端口监示器UI DLL必须定义的函数:函数名称描述DllEntryPointDLL入口点,通常称为DLLMain,它在平台的SDK文档中描述AddPortUI创建一个端口并通过显示一个通话框获得配置信息ConfigurePortUI 配置一个前面增加的端口DeletPortUI删除一个端口InitializePrintMonitorUI 初始化端口监示器的DLL8.2.4.3端口监示器服务器DLL函数下面的表中列出了端口监示器服务器DLL必须定义的函数:函数名称描述DllEntryPointDLL入口点,通常称为D
37、LLMain,它在平台的SDK文档中描述ClosePort关闭一个端口,在没有打印机与它连接时EndDocPort在端口上执行打印作业完成的任务EnumPorts枚举打印机可用的服务器上的端口GetPrinterDataFromPort(可选)发送一个I/O控制代码到端口驱动程序并返回结果InitializePrintMonitor2初始化打印监示器并返回一个实例句柄OpenPort打开一个打印机端口ReadPort从一个打印机端口读数据SetPortTimeOuts(可选)在一个打开的端口上设置超时值StartDocPort执行在一个端口上要开始打印作业的任务WritePort向打印机端口写
38、数据XcvClosePort在端口管理完成之后关闭一个端口XcvDataPort处理端口管理任务XcvOpenPort因为管理目的打开一个端口8.2.5初始化打印监示器当假脱机调用LoadLibrary以装载一个打印监示器DLL,系统立即调用DLL的 DllEntryPoint函数。有一个一般情况都比较好的方法是,对入口函数都调用 DisableThreadLibraryCalls函数(在平台的SDK文档中有描述),这样DLL就在 线程被创建或删除时就不会没有通知到。每一个DLL导出一个初始化函数,它在假脱机调用LoadLibrary之后调用。语言 监示器DLL及端口监示器服务器DLL导出一个
39、InitializePrintMonitor2函数。 端口监示器 UI DLL 导出一个 InitaializePrintMonitorUI 函数。这两个初始化函数负责给打印监示器定义的其余的函数返回指针,这样假脱机可 以调用他们。初始化函数可以执行装载时的初始化操作。显示器的 InitalizePrintMonitor2函数返回一个监示器的实例句柄。监示器应当分配本 地内存以存储特定实例的信息,并使用监示器句柄作为一个分配内存的标识符。第一次调用假脱机时,它装载所有的已经被安装的监示器DLL。在调用了监示器 函数之后,假脱机调用每一个端口监示器的EnumPorts函数,它枚举监示器支持 的端
40、口。(一个监示器支持一个端口,是看是否该端口已被加到监示器的数据库 中,如在增加一个端口中所描述的。)每一个支持的端口这时才被打开,如在打 开及关闭端口部分中所描述的。8.2.6打开及关闭一个端口在增加一个端口之后,如在增加端口部分所描述的,假脱机就能通过调用合适的 语言监示器的OpenPortEx函数打开它。语言监示器用OpenPortEx函数以创建并返回端口句柄。通常,语言监示器调用 它相关的端口监示器的OpenPort函数,并且语言监示器只返回从端口监示器的 OpenPort函数获得的句柄。如果语言监示器与一个端口不相关,假脱机直接调用端口监示器的OpenPort函 数。假脱机不允许在同
41、一时间有多于一个的通道。这样,当它在一个特殊的监示器中 调用OpenPortEx(或OpenPort)之后,就不会在关闭它之前企图打开同一个端口。在一个端口被打开之后,假脱机能调用附加的函数以打印作业,如在打印一个打 印作业部分中所描述的,用端口的句柄作为一个输入的参数。应当编写一个监示 器,在一个端口被打开之后,假脱机可以在关闭端口之前发送多个打印作业。若一个作业必须通过一个不同的语言监示器发送,如果没有与端口相关的打印队 列或者当系统关闭时,则假脱机关闭一个端口。为关闭端口,假脱机调用语言监 示器的ClosePort函数,该函数使端口被打开时创建的句柄无效。语言监示器通 常调用CloseP
42、ort函数,该函数是由它相关的端口监示器定义的。8.2.7打印一个打印作业在一个端口被打开之后,如在打开及关闭端口部分所描述的,假脱机可以发送打 印作业到端口。每个打印作业通过假脱机调用语言或端口监示器的StartDocPort或EndDocPort 函数来被分隔开。假脱机在打印处理器调用假脱机的StartDocPrinter及 EndDocPrinter函数时调用这些函数,这些函数都在平台的SDK文档中有描述。 在StartDocPort及EndDocPort函数的范围之间,可以出现对监示器的 WritePort,ReadPort, GetPrinterDataFromPort 函数的不限次
43、数的调用。这些函数中的每一个都需要由OpenPortEx(或OpenPort)返回的端口句柄做为一 个输入参数来指定。通常,语言监示器通过调用在它的相关的端口监示器中的相 同名字的函数来实现每一个函数。当假脱机调用一个语言监示器的WritePort函数以发送数据流到一个端口,函数 经常增加一些特定语言的信息(如PJL命令)到收到的数据流中,并且是在它被传 送到相关联的端口的WritePort函数之前。ReadPort函数用于获得双向打印机硬件的状态信息,双向打印机硬件的语言监 示器可以通过调用SetPort向假脱机发送,在平台的SDK文档中描述。假脱机不 调用ReadPort函数。如果打印机硬
44、件是双向的,它的语言监示器或端口监示器应当支持 GetPrinterDataFromPort 函数。语言监示器的 GetPrinterDataFromPort 函数应 当接受一个注册表的值名称作为输入,并从那个名称(一般是调用相关端口的 WritePort及ReadPort函数)获得一个值并将值返回给调用者。一个端口监示器 的GetPrinterDataFromPort函数应当接受一个I/O控制的代码作为输入,调用 DeviceIoControl(在平台的SDK文档中有描述)以传递控制代码到端口的驱动程 序,并返回结果。8.2.8管理端口端口管理活动由增加端口、配置端口及删除端口等对应用程序(
45、如打印文件夹) 的响应活动构成。这些端口管理活动被端口监示器处理,不是语言监示器,并需 要管理员的优先权限。对存储端口配置信息有特殊的规则。一个附加的、可选的管理活动包括设置端口超时值。8.2.8.1增加端口增加一个端口由存储端口的名字及用户可修改的在端口监示器服务器DLL的本 地存储中或注册表中的配置信息构成。当应用程序调用打印假脱机的AddPort函数(在平台的SDK文档中描述),它指定 端口监示器的名称作为函数的参数。假脱机调用包含在指定的端口监示器UI DLL 中的AddPortUI函数。端口监示器的UI DLL的AddPortUI函数应当执行下面的操作:1. 调用打印假脱机的OpenPrinter函数(在平台的SDK文档中有描述),它引起 端口监示器服务器DLL中的XcvOpenPort被调用。2. 多次调用打印假脱机的xcvData函数,以请求端口监示器服务器DLL增加端 口并在UI DLL和服务器DLL之间传递配置信息。XcvData函数调用服务器DLL 的XcvDataPort函数。AddPortUI函数通常获得从用户显示对话框栏显示配置信 息。3. 调用打印假脱机的ClosePrinter函数(在平台的SDK文档中描述),它引起端 口监示器服务
链接地址:https://www.31ppt.com/p-5302100.html