文档库 最新最全的文档下载
当前位置:文档库 › 定制微软的打印机驱动程序

定制微软的打印机驱动程序

定制微软的打印机驱动程序
2
推荐微软统一驱动程序(Unidrv)及微软PostScript打印机驱动程序(Pscript)的设计都是基于Windows? NT/Windows? 2000打印机驱动程序体系结构。因此,每一个都是由两部分构成——即一个打印机接口DLL和一个打印机图形DLL。本章讲述怎样定制这些组件。
为提供对Unidrv或Pscript的打印机接口DLL的定制,必须提供一个或多个用户接口的插件。可以使用这些插件来修改驱动程序的用户接口,并对某个打印机事件提供附加的处理。
为提供对Unidrv或Pscript的打印机图形DLL的定制,必须提供一个或多个绘制插件。可以用这些插件去修改将要发送到打印机假脱机中的在打印机作业数据流中的数据。
本章也解释了怎样实现打印机驱动程序的COM接口,它被插件用于与打印机驱动程序之间的通讯,也解释了如何安装定制的驱动程序组件。


7.1用户接口插件
这一节包含如下一些解释怎样开发用户接口插件的主题:
7.1.1用户接口插件介绍
7.1.2UI插件的例子
7.1.3UI插件的COM接口
7.1.4提供DEVMODE结构附加项
7.1.5从UI插件存取驱动程序设置
7.1.6修改一个驱动程序提供的属性表单页面
7.1.7增加新的属性表单页面
7.1.8定制其他的打印机接口操作


7.1.1用户接口插件介绍
当增加对一新的微软统一驱动程序(Unidrv)或者微软Postscript打印机驱动程序(Pscript)打印机设备的支持,可以通过修改打印机的属性表单或文档的属性表单来定制驱动程序的用户接口。
可以通过提供一个用户模式的DLL来完成这些,这一DLL即指的是用户接口的插件,或称UI插件。
一个UI插件可以通过增加、删除、或者替换在属性表单中的“设备设置(Device Settings)”页面的选项来修改打印机属性表单。它也可以增加新的页面。同样,插件可以通过增加、删除、替换在属性表单的“布局(Layout)”、“纸张/质量(Paper/Quality)”、“高级(Advanced)”页面的选项来修改文档属性表单,或者它也可以增加新页。
UI插件被称为Unidrv或Pscript的打印机接口DLL,用了一套COM接口。打印机接口DLL是通过使用CPSUI来实现的,并且一个UI插件通过驱动程序的打印机接口DLL与CPSUI进行间接的交互。因此,在开发UI插件之前,阅读CPSUI一章是非常有益的。
除修改打印机驱动程序的用户接口外,一个UI插件可以执行其他的操作,如处理某个打印机事件并报告被支持的能力。更多的信息,请参考定制其他打印机接口操作部分的内容。


7.1.2 UI插件的例子
在该DDK中提供了用户接口插件的源代码实例。其代码包含在\oemui源代码目录的子目录中,并且创建了一个可以与Unidrv使用的插件。


7.1.3 UI插件的COM接口

下面的COM接口是为微软打印机驱动程序与UI插件之间的通讯定义的:
IPrintOEMUI COM Interface——允许为Unidrv或Pscript的打印机接口DLL调用UI插件。
IPrintOemDriverUI COM Interface——对UI插件提供实用的操作。
7.1.3.1 IPrintOemUI COM 接口
IPrintOemUI COM接口实际提供了一种Unidrv或Pscript的打印机接口DLL与UI插件通讯的一种手段。IPrintOemUI COM由每一个UI插件来实现的。
下面的表格列出并描述了所有的由IPrintOemUI接口提供的方法。UI插件必须定义所有列出来的方法。如果一种方法不需要,它可以只返回E_NOTIMPL。
方法 描述
IPrintOEMUI::CommonUIProp
允许一个用户接口插件修改一个已经存在的属性表单页面或者文档的属性表单页面
IPrintOEMUI::DeviceCapabilities
允许一个用户插件去指定定制的设备能力
IPrintOEMUI::DevicePropertySheets
允许一个用户插件给一个打印机设备的打印机属性表单增加新页
IPrintOEMUI::DevMode
在一个用户接口插件上执行操作的私有DEVMODE成员
IPrintOEMUI::DevQueryPrintEx
允许一个用户插件帮助确定是否一个打印作业是可打印的
IPrintOEMUI::DocumentPropertysheets
允许一个用户插件给一个打印机设备的文档属性表单增加新页面
IPrintOEMUI::DriverEvent
在处理驱动程序专用的、需要打印机驱动程序行为的事件时,由打印假脱机调用
IPrintOEMUI::FontInstallerDlgProc
替换Unidrv字体安装程序的用户接口
IPrintOEMUI::GetInfo
(需要实现部分)返回一个用户接口插件标识符的信息
IPrintOEMUI::PrinterEvent
允许一个用户接口插件处理打印机事件
IPrintOEMUI::PublishDriverInterface
(需要实现部分)提供一个对Unidrv或Pscript驱动程序的IPrintOemDrvierUI COM接口的指针
IPrintOEMUI::QuerycolorProfile
允许一个打印机接口DLL为用户的色彩管理指定一个ICC的初始化文件profile
IPrintOEMUI::UpdateExternalFonts
允许一个打印机接口DLL修改一个打印机的Unidrv字体格式文件(.uff文件)
IPrintOEMUI::UpgradePrinter
允许一个用户接口插件升级存储于注册表中的设备选项值

更多的信息,可参考实现打印机驱动程序COM接口部分。


7.1.3.2 IPrintOemDriverUI COM接口
IPrintOemDriverUI COM接口允许一个UI插件去查看并修改由Unidrv及Pscript打印机接口DLL管理的信息。
下表列出并描述了所有由IPrintOemDriverUI接口定义的方法:
方法 描述
IprintOemDriverUI::DrvGetDriverSetting
允许一个用户接口插件获得当前打印机特性的状态及其他内部信息
IprintOemDriverUI::DrvUpdateUISetting
允许一个用户接口插件通知驱动程序修改了的用户接口选项
IprintOemDriverUI::DrvUpgradeRegistrySetting
允许一个用户接口插件修改存储于注册表中的设备设置

更多的信息,参考实现打印

机驱动程序COM接口部分。


7.1.4提供DEVMODE结构附加项
用户接口插件可以向DEVMODE结构增加附加的私有成员,如图所示:


插入图???


一个UI插件可以使用这些私有的DEVMODE成员存储与定制的打印机选项相关的值。通过修改驱动程序提供的属性表单页面,或增加新属性表单页面时,插件使得这些选项对一个用户可用。
如果UI插件增加一个私有的DEVMODE成员,被增加的成员必须通过OEM_DMEXTRAHEADER结构来预置。
不需要向DEVMODE结构增加成员,但如果做了,插件必须实现IPrintOemUI::DevMode方法。依赖于输入的参数,这一方法的目的是返回另外增加的DEVMODE成员的初始化、转换或有效的大小。


7.1.5从UI插件存取驱动程序设置
一个用户接口插件可以获得当前打印机特性及其他内部信息的状态。IPrintOemDriverUI::DrvGetDriverSetting COM接口方法是在为微软打印机驱动程序的打印机接口DLL中实现的并能被UI插件调用。
另外,下面的方法允许UI插件修改驱动程序信息。
IPrintOemDriverUI::DrvUpdateUISetting允许一个UI插件在用户已经修改了驱动程序的设定时通知驱动程序。
IPrintOemDriverUI::DrvUpgradeRegistrySetting允许一个UI插件修改在注册表中的设备设定,这样由旧的驱动程序版本使用注册表设定就可以被修改。


7.1.6修改一个驱动程序提供的属性表单页面
一个UI插件可以直接通过实现IPrintOemDriverUI::CommonUIProp方法及一个回调函数来修改Unidrv或Pscript提供的属性表单页面。
IPrintOemDriverUI::CommonUIProg方法被UI插件使用以指定一套CPSUI可以在打印机属性表单的“设备设置(Device Settings)”页面或者文档属性表单的“布局(Layou)”“纸张/质量(Paper/Quality)”“高级(Advanced)”页面中增加、删除或替换的选项项目。
回调函数,其类型为OEMCUIPCALLBACK,用于处理用户对定制选项项目的修改。


增加选项项目
UI插件必须描述新的选项项目,这是通过将它们放置于一个由驱动程序提供的OPTITEM结构的数组中来完成的。驱动程序打印机接口DLL两次调用UI插件的IPrintOemDriverUI::CommonUIProp方法。该方法第一次被调用时,它应当返回需要OPTITEM结构的数目,驱动程序对OPTITEM数组分配空间并在一个OEMCUIPPARAM结构中描述该数组。然后,驱动程序再次调用该方法,提供OEMCUIPPARAM结构的地址,这样该方法可以用选项描述去装载OPTITEM结构。


删除选项项目
从一个Unidrv或Pscript提供的属性表单页中删除一个选项,UI插件的IPrintOemDriverUI::CommonUIProp方法可以遍历由OEMCUIPPARAM结构指向的OPTIITEM结构的数组,可以设置OPTITEM结构的OPTIF_HIDE标识(注意,这种做法实际上并没有删除选项,它只是对用户隐藏了选项,

这样它默认的值就不能被改变)。


替换选项项目
为在一个Unidrv或Pscript提供的属性表单页中替换一个选项,应当根据在删除选项项目部分的教学内容去删除已经存在的选项项目,然后根据增加选项项目部分的内容以创建一个新的选项项目以替换旧的项目。


处理对定制选项值的修改
为了处理用户对定制选项项目的修改,必须至少提供一个回调函数。可以指定一个单一的回调函数用于处理对文档属性表单及打印机属性表单的处理,或者可以分别为它们各自指定一个单独的函数,这些回调函数属于OEMCUIPCALLBACK类型。
对一个回调函数的指定只需将它的地址设置在OEMCUIPPARAM结构中即可。UI插件作为对自身的IPrintOemDriverUI::CommonUIProp方法的输入收到这一结构的地址。
当一个用户打开打印机的属性表单或者文档属性表单并修改选项时,CPSUI调用打印机驱动程序的打印机接口DLL。这一DLL处理包含于它自身的OPTITEM结构中的选项值,然后,对每一个UI插件,打印机接口DLL调用由IPrintOemDriverUI::CommonUIProp 前面指定的OEMCUIPCALLBACK类型的回调函数。


7.1.7增加新的属性表单页面
如果想给打印机接口为Unidrv及Pscript提供的属性表单增加一个新的页面,UI插件必须实现下面的IPrintOemUI方法:
IPrintOemDriverUI::DevicePropertySheets
用于给打印机属性表单增加页面,当在一个用户从打印文件夹或打印机窗口选择了“属性(Properties)”菜单项时显示,或者当一个应用程序调用了PrinterProperties函数时显示(在平台的SDK文档中有描述)。
IPrintOemDriverUI::DocumentPropertySheets
用于给文档的属性表单增加新页,它在一个用户从打印文件夹或打印机窗口上选择了“打印机优选项(Printer Preference)”的菜单选项时或者应用程序调用了DocumentProperties/AdvancedDocumentProperties函数(在平台的SDK文档中有描述)。
如果实现了其中的一种方法,通常会提供一个_CPSUICALLBACK类型的回调函数以处理用户的修改。这一回调函数必须调用IPrintOemDriverUI::DrvUpdateUISetting以在与用户接口相关的设定值被修改后通知驱动程序,而这个设定值是要存储于驱动程序的DEVMODE结构或注册表的关键字中。


7.1.8定制其他的打印机接口操作
一个UI插件可选择性地实现下面的任一种IPrintOemDriverUI方法:
IPrintOemDriverUI::DeviceCapabilities
IPrintOemDriverUI::DevQueryPrintEx
IPrintOemDriverUI::PrinterEvent
IPrintOemDriverUI::UpgradePrint
这些方法等同于由Unidrv及Pscript使用的用户模式的打印机接口DLL导出的相同名称的函数。这些定制的方法不替换在驱动程序的打印机接口DLL中的等同函数。在每一种情况下,打印机接口DLL函数被首选调用,然后驱动程序

调用插件的定制方法。


7.2绘制插件
下面的主题描述了怎样定制打印机绘制操作:
7.2.1绘制插件介绍
7.2.2绘制插件实例
7.2.3绘制插件的COM接口
7.2.4定制的DDI函数
7.2.5定制的PDEV结构
7.2.6从绘制插件存取驱动程序设置
7.2.7特定Pscript的定制绘制
7.2.8特定Unidrv的定制绘制


7.2.1绘制插件介绍
当增加对一个新的打印机设备的微软通用打印机驱动程序(Unidrv)或微软PostScript打印机驱动程序(Pscript)的支持,可以实现COM接口方法以修改打印机发送给打印假脱机的数据。
可以通过提供用户模式的DLL来完成这一定制。这个DLL即被看作为一绘制插件。
有两种类型的定制被支持:
提供一些DDI绘制函数的定制版本
实现特定Unidrv或特定Pscript的COM接口方法,它们在修改被绘制的图象数据或扫描行数据流,或者在专用的注入点插入Postscript代码,这些都是在数据流被发送到假脱机之前进行的。


7.2.2绘制插件实例
这一DDK也提供有绘制插件的源代码示例。代码包含于\oemuni源代码的子目录中并创建了一个可用于Unidrv的插件。


7.2.3绘制插件的COM接口
下面的COM接口是为微软打印机驱动程序及绘制插件之间的通讯定义的。
IPrintOemUni COM接口 ——允许Unidrv的打印机图形DLL调用绘制插件。
IPrintOemDriver COM接口 ——给Unidrv的绘制插件提供实用操作。
IPrintOemPS COM接口 ——允许Pscript的打印机图形DLL调用绘制插件。
IPrintOemDriverPS COM接口 ——给Pscript的绘制插件提供实用操作。


7.2.3.1 IPrintOemUni COM接口
IPrintOemUni COM接口是Unidrv的打印机图形DLL与绘制插件通讯的手段。IPrintOemUni COM接口是通过每一个绘制插件来实现的。
下面列出并描述了所有由IPrintOemUni COM接口提供的方法。绘制插件必须定义列出所有的方法,如果一个方法不需要,则它必须返回E_NOTIMPL。
方法 描述
IPrintOemUni::CommandCallback
允许一个绘制插件提供动态产生的打印机命令
IPrintOemUni::Compression
允许一个绘制插件提供定制的位图压缩方法
IPrintOemUni::DevMode
在绘制插件的私有DEVMODE成员上的执行操作
IPrintOemUni::DisableDriver
释放由绘制插件IPrintOemUni::EnableDriver方法提供的插件
IPrintOemUni::DisablePDEV
允许一个绘制插件删除私有的由IPrintOemUni::EnablePDEV方法分配的PDEV结构
IPrintOemUni::DownloadCharGlyph
允许一个绘制插件给打印机下载专用的软字体字符
IPrintOemUni::DownloadFontHeader
允许一个绘制插件下载字体头信息给打印机
IPrintOemUni::DriverDMS
允许一个绘制插件指明它将用一个设备管理的绘制表面
IPrintOemUni::EnableDriver
允许一个绘制插件分出(hook out)一些DDI函数
IPrintOemUni::EnablePDEV


允许一个绘制插件创建它自已的PDEV结构
IPrintOemUni::FilterGraphics
允许一个绘制插件修改扫描行数据并将它发送到假脱机
IPrintOemUni::GetImplementedMethod
(需要实现)允许Unidrv决定哪一个IPrintOemUni接口方法已经被绘制插件所实现
IPrintOemUni::GetInfo
(需要实现)返回绘制插件的标识信息
IPrintOemUni::HalftonePattern
允许一个绘制插件创建或修改一个过渡调色调色板,并且在它被用于过渡调色的操作之前
IPrintOemUni::ImageProcessing
允许一个绘制插件修改图像位图数据,以执行色彩格式或过渡调色
IPrintOemUni::MemoryUsage
允许一个绘制插件指定被IPrintOemUni::ImageProcessing方法需要的内存的总量
IPrintOemUni::OutputCharStr
允许一个绘制插件控制字体符号的打印
IPrintOemUni::PutlishDriverInterface
(需要实现)提供一个Unidrv驱动程序的IPrintOemDriverUni COM接口
IPrintOemUni::ResetPDEV
允许一个绘制插件重置它的PDEV结构
IPrintOemUni::SendFontCmd
允许一个绘制插件修改一个打印机的字体选择命令并然后将它发送到打印机
IPrintOemUni::TextOutAsBitmap
允许一个绘制插件创建一个文本字符串的位图图像
IPrintOemUni::TTDownloadMethod
允许一个绘制插件去指明Unidrv应当为一个专用的TrueType字体使用的格式
IPrintOemUni::TTYGetInfo
允许一个绘制插件给Unidrv提供与打印机相关的文本信息

更多的信息,可以参考实现打印机驱动程序COM接口部分。


7.2.3.2 IPrintOemDriver COM接口
IPrintOemDriver COM接口提供一个绘制插件,它能够存取Unidrv的图形DLL提供的功能操作。这些操作包括发送数据流到打印机假脱机并获取驱动程序管理的信息。
下表列出并描述所有的由IPrintOemDriverUni接口定义的方法。
方法 描述
IPrintOemDriverUni::DrvGetDriverSetting
返回打印机特性的当前状态及其他内部信息
IPrintOemDriverUni::DrvGetGPDData
使绘制插件获得在打印机GPD文件中定义的数据
IPrintOemDriverUni::DrvGetStandardVariable
使绘制插件获得Unidrv的标准变量的当前值
IPrintOemDriverUni::DrvUniTextOut
使绘制插件使用一个设备管理的绘制表面以很容易地输出文本字符串
IPrintOemDriverUni::DrvWriteSpoolBuf
发送打印机数据到假脱机
IPrintOemDriverUni::DrvXMoveTo
通知Unidrv关于x位置的变化
IPrintOemDriverUni::DrvYMoveTo
通知Unidrv关于y位置的变化

更多的信息,参考实现打印机驱动程序COM接口部分。


7.2.3.3 IPrintOemPS COM接口
IPrintOemPS COM接口是Pscript的打印机图形DLL与绘制插件通讯的手段。IPrintOemPS接口是由每一个绘制插件来实现的。
下表列出并描述了所有由IPrintOemPS提供的接口。绘制插件必须定义所有的被列出的方法。如果一个方法是不需要的,则它应返回E_NOTI

MPL。
方法 描述
IPrintOemPS::Command
允许一个绘制插件插入postscript命令到打印作业的数据流中
IPrintOemPS::DevMode
在绘制插件的DEVMODE的私有变量上的执行操作
IPrintOemPS::DisableDriver
释放由绘制插件的IPrintOemPS::EnableDriver分配的资源
IPrintOemPS::DisablePDEV
允许一个绘制插件删除私有的PDEV结构,该结构是由它的IPrintOemPS::EnablePDEV方法分配的
IPrintOemPS::EnableDriver
允许一个绘制插件分出一些DDI函数
IPrintOemPS::EnablePDEV
允许一个绘制插件创建它的PDEV结构
IPrintOemPS::GetInfo
(需要实现)返回绘制插件的标识信息
IPrintOemPS::PublishDriverInterface
(需要实现)提供一个Pscript驱动程序的指向IPrintOemPS COM接口的指针
IPrintOemPS::ResetPDEV
允许一个绘制插件重置它的PDEV结构

更多的信息,参考实现打印机驱动程序COM接口部分的内容。


7.2.3.4 IPrintOemDriverPS COM接口
IPrintOemDriverPS COM接口提供一个可以存取Pscript的、由打印机图形DLL提供的功能进行操作的绘制插件。这些操作包括发送数据流到打印机假脱机以及获取驱动程序管理的信息。
下面的表格列出并描述了由IPrintOemDriverPS接口定义的方法:
方法 描述
IPrintOemDriverPS::DrvGetDriverSetting
返回打印机特性的当前信息以其他内部信息
IPrintOemDriverPS::DrvWriteSpoolBuf
发送打印机数据到假脱机

更多的信息,参考实现打印机驱动程序COM接口部分的内容。


7.2.4定制的DDI函数
一个绘制插件可以分出一些DDI函数,提供这些函数的定制实现。为提供定制的函数,绘制插件必须实现IPrintOemUni::EnableDriver或IPrintOemPS::EnableDriver方法,这两个方法被填写在DRVENABLEDDATA结构并具有每一个函数的地址。
一个绘制插件可以分出一个DDI函数,但只是在该函数是由Unidrv或Pscript驱动程序定义时。对这些函数的列表,参考DDK中包括的IPrintOemUni::EnableDriver或IPrintOemPS::EnableDriver。
如果提供一个特殊的定制的分出函数,该函数优先于驱动程序的等同DDI函数。当设计一个定制的分出函数,可以有下面的选项:
分出函数可以完全在内部处理DDI操作。
分出函数可以回调打印机驱动程序等同的DDI函数。
通过调用驱动程序的DDI函数,分出函数可以执行预处理或后处理的函数参数,但是仍然允许驱动程序实际执行DDI操作。对绘制插件的IPrintOemUni::EnableDriver或IPrintOemPS::EnableDriver方法的一个参数是DRVENABLEDDATA 结构包含的指向驱动程序DDI函数的指针。如果想回调这些函数,应当存储这些结构的内容。
对来说,也许有必要提供一个定制的PDEV结构。可以通过每一个分出函数作为输入接收的SURFOBJ结构指针,从一个DDI的分出函数中引用这一结构。特定地,

SURFOBJ结构的dhpdev成员指向一个DEVOBJ结构,并且DEVOBJ结构的pdevOEM成员指向定制的PDEV结构。


7.2.5定制的PDEV结构
绘制插件通过实现下面的方法来支持私有的PDEV结构:
IPrintOemUni::EnablePDEV或IPrintOemPS::EnablePDEV
IPrintOemUni::DisablePDEV或IPrintOemPS::DisablePDEV
IPrintOemUni::ResetPDEV或IPrintOemPS::ResetPDEV
PDEV结构是一个一般的项目,它指向一个私有的,本地定义的结构并由定义它的模块来使用。通常,它用于存储物理设备特征。每一个打印机驱动程序,以及每一个绘制插件,定义它自已的PDEV结构。没有被定义的全局范围的“PDEV”类型的结构。


7.2.6从绘制插件存取驱动程序设置
一个绘制插件可以获取打印机特性的当前状态及其他内部驱动程序信息。下面的COM接口方法在微软打印机驱动程序内实现在方法可以被绘制插件来调用:
由Unidrv实现的方法:
IPrintOemDriverUni::DrvGetDriverSetting
IPrintOemDriverUni::DrvGetStandardVariable
IPrintOemDriverUni::DrvGetGPDData


由Pscript实现的方法:
IPrintOemDriverPS::DrvGetDriverSetting


7.2.7特定Pscript的定制绘制
Pscirpt允许特定设备的定制代码注入Postscript命令到Pscript发送给打印机设备的数据流中。如果想提供这种类型的定制代码,必须提供一个绘制插件以实现IPrintOemPS::Command方法。
Pscript在打印机作业数据流的很多点调用IPrintOemPS::Command方法。函数的参数之一指定了一个表示当前在数据流中点的位置的索引值。函数的每次调用,它可以检验索引的值并提供另外的数据流或者不提供。


7.2.8特定Unidrv的定制绘制
下面的主题提供了关于Unidrv允许绘制插件执行的操作的类型的信息:
7.2.8.1定制的色彩格式
7.2.8.2定制的过渡调色
7.2.8.3定制的数据流压缩
7.2.8.4定制的数据流过滤
7.2.8.5定制的字体管理
7.2.8.6动态产生的打印机命令
7.2.8.7处理设备管理的表面


7.2.8.1定制的色彩格式
Unidrv支持好几种色彩格式,这些色彩格式在微软统一打印机驱动程序一章的处理色彩格式中列出。对这些格式来说,Unidrv在向打印机发送之前,转换GDI位图到正确的格式。如果打印机接受Unidrv不支持的格式,必须提供一个交换插件以实现IPrintOemUni::ImageProcessing方法。
如果实现IPrintOemUni::ImageProcessing方法,并且用户已经选择了Unidrv不能处理的色彩格式(色彩模式选项),这样,每次一个缓冲区中的GDI位图数据准备打印时,Unidrv调用该方法并传寄位图的地址作为一个输入的参数。该方法必须转换位图到专用的格式,如果需要,将执行定制的过渡调色操作,并调用IPrintOemUni::DrvWriteSpoolBuf方法以发送被修改了的位图到打印机假脱机。它也必须调用IPrintOemUni:

:DrvXMoveTo及IPrintOemUni::DrvYMoveTo方法以修改光标的位置。更多的关于这些操作的信息,参考关于IPrintOemUni::ImageProcessing的描述。
如果一个绘制插件实现IPrintOemUni::ImageProcessing,它也能实现IPrintOemUni::MemoryUsage方法。


7.2.8.2定制的过渡调色
如在微软统一打印机驱动程序一章中的用Unidrv过渡调色部分所解释的,Unidrv允许GDI执行过渡调色操作,也可以由打印机设备、或由定制的驱动程序代码来执行。本部分解释了怎样在定制的驱动程序代码中执行过渡调色的操作。
有两种类型可用的定制:
定制的过渡调色模式
定制的过渡调色方法


定制的过渡调色模式
过渡调色模式可以在资源DLL中指定,或者它们可以由一个实现IPrintOemUni::HalftonePattern方法的绘制插件来产生。如在微软统一驱动程序一章用Unidrv过渡调色中所解释的,实现IPrintOemUni::HalftonePattern有两个原因:
1.定制的模式是在一个资源DLL中提供的,并且该模式是加密的。
2.定制的模式不是在资源DLL中提供的,相反,是由IPrintOemUni::HalftonePattern产生的。
IPrintOemUni::HalftonePattern方法的目的是给Unidrv返回一个可用的取中色模式,它按次序传递给GDI。该方法可以解码一个以加密格式存储于资源DLL中的模式,或者它可以在执行过程中产生一个模式。
如果实现IPrintOemUni::HalftonePattern,GPD文件必须在每一个取中色的的*Option条目中包括一个*HTCallbackID属性,这一个*Option条目是用于使用哪一种定制的模式时指定过渡调色的方法。更多的关于这一属性的信息,可参考第4章微软统一打印机驱动程序的取中色间特性的选项属性部分。


定制的过渡调色方法
对一个使用Unidrv的打印机来说,提供实现定制的过渡调色的方法的代码需要下面的步骤:
提供一个实现IPrintOemUni::ImageProcessing方法的绘制插件。
在打印机的GPD文件中包括一个过渡调色的*Feature条目,用每一个包含*Option的条目表示一个过渡调色方法。(也可以包括标准的或定制的过渡调色方法)
IPrintOemUni::ImageProcessing方法作为输入收到GDI位图,该方法必须执行过渡调色操作,基于当前选择的过渡调色方法,并返回结果位图到Unidrv。
如果一个绘制插件这现了IPrintOemUni::ImageProcessing,它也可以实现IPrintOemUni::MemoryUsage。
更多的关于过渡调色的信息,参考第4章微软统一打印机驱动程序中的用Unidrv过渡调色部分的内容。


7.2.8.3定制的数据流压缩
Unidrv允许数据压缩操作由定制的代码来执行。
为执行定制的压缩操作,必须做下面的内容:
提供一个实现IPrintOemUni::Compression方法的绘制插件。
在GPD文件中包括一个CmdEnableOEMComp命令条目。更多的

关于这一命令的信息,参考第4章微软统一打印机驱动程序中的光栅数据压缩命令部分的内容。
IPrintOemUni::Compression方法作为输入收到扫描行数据。该方法必须压缩数据并将结果返回到Unidrv。CmdEnableOEMComp命令条目指定必须发送到打印机的命令,从而使打印机可以接收这些压缩数据的命令。对要发送到打印机的每一个扫描行,Unidrv调用IPrintOemUni::Compression以压缩这些扫描行,然后,如果这是唯一可用的压缩方法,Unidrv在压缩数据之后,向打印机发送由CmdEnableOEMComp命令条目指定的命令。
如果打印机小驱动程序包括允许Unidrv支持的压缩方法的GPD条目,则Unidrv将对每一个扫描行数据试用每一种压缩算法并选择产生最好结果的压缩算法。更多的关于Unidrv的压缩能力的信息,参考第4章微软统一打印机驱动程序中的压缩光栅数据部分的内容。
在同一时间,只能有一种定制压缩算法被允许。


7.2.8.4定制的数据流过滤
Unidrv允许定制的代码执行最终图像数据的后处理,并在其被送至假脱机之前。这样的处理包括删除相邻的点或者其他任何类型的Unidrv不能提供的数据过滤操作。
为执行最终的图像数据的后处理,必须提供一个实现IPrintOemUni::FilterGraphics方法的绘制插件。
IPrintOemUni::FilterGraphics方法接收扫描行数据作为输入,该方法必须处理数据并将数据通过调用IPrintOemUni::DrvWriterSpoolBuf发送到假脱机。如果IPrintOemUni::FilterGraphics方法被实现,Unidrv不支持假脱打印机数据。相反,它发送每一个数据块到IPrintOemUni::FilterGraphics方法。


7.2.8.5定制的字体管理
Unidrv对PCL打印机支持下载的软字体作为位图或TrueType字体的轮廓。对设备字体,Unidrv支持PCL、CAPSL以及PPDS打印机命令格式。对其他格式,定制的字体管理代码必须被在一个绘制插件中提供,下面的一系列IPrintOemUni方法,可以被实现。


IPrintOemUni::DownloadFontHeader
用于从Unidrv获得软字体的头信息并将信息下载到打印机


IPrintOemUni::DownloadCharGlyph
用于给打印机下载一个软件字体的字符集


IPrintOemUni::OutputCharStr
用于控制字母的打印


IPrintOemUni::SendFontCmd
用于修改一个打印机的设备字体选择命令,如果必要,然后就发送它到打印机。


IPrintOemUni::TextOutAsBitmap
用于创建文本字符串的位图图像


IPrintOemUni::TTDownloadMethod
用于指定Unidrv在向打印机发送专用的软件字体时应当使用的符号格式。
Unidrv提供了一个回调函数,UNIFONTOBJ_ GetInfo,那个绘制的插件可以调用获得字体或字符的信息。
对设备字体,字体描述必须被以Unidrv字体规格文件(.ufm文件)及翻译表文件(.gtt文件)的格式来提供。
对Cartridg

e字体,可以在资源DLL中提供字体描述并在GPD文件中用Cartridge字体条目来指定。字体描述可以Unidrv字体格式文件(.uff文件)的形式提供。
对可下载的PCL软件字,字体描述必须以Unidrv字体格式文件(.uff文件)来提供。


Unidrv字体规格文件
打印机支持的每一种设备字体必须用Unidrv字体规格文件(.ufm文件)来表示。.ufm文件是一个用在DDK的打印机驱动程序函数及结构一章中的Unidrv字体规格中描述的结构组建的二进制文件。.ufm中的第一个结构是UNIFM_HDR,它包含有到文件的其他结构的偏移量。
更多的关于创建.ufm文件的信息,可参考第四章中的微软小驱动程序开发工具部分的内容。
Unidrv也支持.ifi文件,是一种为Windows NT 4.0创建的字体规格文件。


字符翻译表文件
打印机支持的每一种设备字体文件必须用一个字符翻译表文件(.gtt文件)来表示,一个.gtt文件是一个用在Unidrv字符翻译表一章中的打印机驱动程序函数及结构部分中描述的结组构建的二进制文件。.gtt中的的第一个结构是UNI_GLYPHSETDATA,它包含有到文件的其他结构的偏移量。
更多的关于创建.gtt文件信息,参考第4章中的微软小驱动程序开发工具部分的内容。
Unidrv也支持为Windows NT 4.0创建的字符翻译文件,它用RLE压缩并具有一个.rle的扩展名。


Unidrv字体格式文件
对那些没有在GPD文件中用字体Cartridge条目指定的Cartridge字体来说,该字体必须以Unidrv字体格式文件(.uff文件)来描述。另外,下载的PCL软字体必须用.uff文件来指定。
一个.uff二进制文件是用下面的结构组建起来的。
Unidrv字体格式结构。它定义了内容及.uff文件的结构。
Unidrv字体规格结构。它定义了每种字体的规格。
Unidrv字符翻译表结构。它定义了字体所用的字符集。
另外,对下载的PCL软字体来说,二进制数据存储于.ufm文件中。
创建.uff文件是商家提供的字体安装软件的责任。Unidrv读取一个打印机的.uff文件以获得字体及字符信息。字体安装程序应当在字体被增加或删除时修改.uff文件内容。更多的关于创建字体安装程序的信息,参考定制的Unidrv的字体安装程序部分的内容。
打印机的所有.uff文件必须被保存在%SystemRoot%\System32\Spool\Drivers\Unifont目录中。为关联单独的.uff文件与专用的打印机,安装软件必须调用SetPrinterData函数(在平台的SDK文档中有描述)以在每一个打印机的注册关键字中创建注册值,并指明每一个值的维持者。
注册表值名称及类型 值定义 维持者
“ExternalFontFile”
REG_SZ
一个.uff文件的文件名,指定当前被安装的字体。字体可以被下载或者包含在一个Cartridge中
字体安装程序
“ExtFontCartFile”
REG_SZ


一个.uff文件的文件名,指定所有所有包含在字体Cartridge中为“ExtFontCartNames”列出的所有字体
字体安装程序
“ExtFontCartNames”
REG_MULTI_SZ
所有的可以被安装在一个打印机上的Cartridge字体
字体安装程序
“FontCart”
REG_MULTI_SZ
当前安装在一个打印机上的所有的字体Cartridge
Unidrv用户接口

在给一个打印机增加了字体Cartridge之后,系统管理者将运行字体安装程序,它负责从由“ExtFontCartFile”指定的.uff文件中拷贝字体描述到由“ExternalFontFile”指定的.uff文件中。同样,字体安装程序必须删除.uff中在一个Cartridge字体被删除时由“ExtFontCartFile”指定的字体描述。


7.2.8.6动态产生的打印机命令
每一次在一个GPD文件中为一个Unidrv的小驱动程序指定打印机命令时,可以采用下面两种方法中的一种:
把命令字符串放于GPD文件中
当将命令字符串放于GPD文件中时,Unidrv在适当的时间发送命令到打印机假脱机。这些命令字符串可以包括标准变量,这些变量在Unidrv发送命令之前都会进行求值。
提供一个回调函数
如果提供一个回调函数,Unidrv在它发送命令时调用该函数,该函数主要负责发送命令到打印机假脱机。这就使得可以包括那些动态产生的命令字符串并然后将它送往打印机。
为设置一个命令字符串在GPD文件中,需要在命令的*Command条目中包括一个*Cmd属性。
为提供动态产生的命令字符串的代码,必须做下面的事情:
提供一个绘制的插件以实现IPrintOemUni::CommandCallback方法。
包括一个*CallbackID命令属性,并包括一个可选的*Param属性,在GPD文件的命令的*Command条目中。
当Unidrv准备发布一个打印机命令,它检查小驱动程序的数据库以确定是否该命令已经用一个*Cmd属性或一个*CallbackID属性指定。在前一种情况下,Unidrv发送命令字符串到打印假脱机;在后一种情况,Unidrv调用IPrintOemUni::CommandCallback方法,传递*CallbackID及*Params值作为输入参数。
打印机命令被在第4章微软打印机驱动程序中讨论过。更多的关于*Cmd、*Callback及*Params属性的信息,同样参考第4章中的命令属性部分。


7.2.8.7处理设备管理的表面
当Unidrv绘制器打印页面图像时,它用GDI管理的绘制表面。所有的图像被作为位图绘制。对设备提供能力不能在此种情形下采用,如绘制向量等。可以对一个设备管理的绘制表面提供定制的驱动程序支持。为支持一个设备管理的表面,必须提供一个插件以实现下面的内容:
对所有的Unidrv支持的DDI绘制函数的一套分出函数。必须能分出下面的这些函数
DrvAlphaBlend
DrvBitBlt
DrvCopyBits
DrvDitherColor
DrvFillPath
DrvGradientFill
DrvLintTo
DrvPl

gBlt
DrvRealizeBrush
DrvStretchBlt
DrvStretchBltROP
DrvStrokeAndFillPath
DrvStrokePath
DrvTextOut
DrvTransparentBlt
IPrintOemUni::EnableDriver方法,它用于向Unidrv提供指向DDI分出函数的指针。
IPrintOemUni::DriverDMS方法,它通知Unidrv一个设备管理的表面被应用,并指定对这一表面哪一个被定义的分出函数将被用到。
当绘制一个设备管理的表面时,分出函数不能回调GDI的以Eng-为前缀的支持服务。但是,它们可以创建一个临时的位图表面,并传递那个表面的句柄到以Eng-为前缀的函数(参考第3章中的绘制一个打印作业部分)。
一个打印作业要被绘制的每一次,都要调用IPrintOemUni::DriverDMS方法,因此绘制插件可以指定对每个作业绘制表面的类型(GDI管理或设备管理)。基于所需要的用户接口上的可选择的选项或者是提供一个用户接口插件以进行表面选择。


在设备管理的表面上绘制文本
绘制插件必须分出Unidrv的DrvTextOut函数(以及其他DDI绘制函数)。为一个设备管理的表面创建文本并包括在以下四个函数之间的相互作用:
Unidrv的DrvTextOut函数
绘制插件的DrvTextOut分出函数
Unidrv的IPrintOemUni::DrvUniTextOut方法
绘制插件的IPrintOemUni::TextOutAsBitmap方法
步骤包括在设备管理的表面上显示文本,如下:
1.GDI调用Unidrv的DrvTextOut函数。
2.Unidrv调用绘制插件的DrvTextOut分出函数。
3.分出函数发送命令到设备以指定文本刷、旋转及裁剪区域。
4.分出函数调用Unidrv的IPrintOemUni::DrvUniTextOut方法,它试图使用可下载的字体到输出文本。这一方法也处理基于字符的剪贴。
5.如果IPrintOemUni::DrvUniTextOut不能用可下载的字体(由于该字体不能获得或者旋转),它调用插件的IPrintOemUni::TextOutAsBitmap方法,它当绘制一个位图来绘制文本。
6.在IPrintOemUni::DrvUniTextOut返回后,DrvTextOut分出函数必须绘制下划线及中横线,基于由DrvTextOut函数的prclExtra参数指定的距形,并使用矢量命令(如果支持)。


7.3实现打印机驱动程序的COM接口
这一部分解释了怎样基于DDK提供的示例代码构建一个插件。也解释了用于打印机驱动程序及插件通讯的调用顺序。提供了下面的主题:
打印机驱动程序的接口标识符
创建插件
从打印机驱动程序存取插件接口
从插件存取打印机驱动程序接口


7.3.1 打印机驱动程序的接口标识符
在prcomoem.h中定义了一套GUID结构,在这些GUID结构中的每一个都是用于打印机驱动程序(Unidrv及Pscript)及插件之间通讯的一个COM接口的接口标识符。
对Windows 2000,定义了下面的GUID:
IDD_IPrintOemUI
IDD_IPrintOemDriverUI
IDD_IPrintOemUni
IDD_IPrintOemDriverUni
IDD_IPrintOemPS
IDD_IPrintOemDriverPS

每一个GUID标识一个接口的版本。对Windows 2000,每一个接口只有一个版本,随着未来的一些版本的操作系统的发布,也许需要去修改一个或多个接口。如果定义了一个新版本的接口,一个新的GUID将被加入到这一列表中。
用户接口插件及绘制插件必须鉴别它们支持的接口版本。打印机驱动程序(Unidrv或Pscript)将调用一个插件的IUnknown::QueryInterface方法(在平台的SDK文档中有描述),指定一个接口标识符作为输入。如果插件支持专用的版本,方法必须返回一个接口的指针并返回有S_OK的状态值。否则,它必须返回E_NOINTERFACE。驱动程序用一个对最新版本的接口标识符开始并继续使用以前版本的标识符调用QueryInterface,直到方法返回S_OK或者驱动程序穷举完列表中的版本标识符为止。
同样,Unidrv及Pscript为IPrintOemDriver、IPrintOemDriverUni及IPrintOemDriverPS COM接口提供IUnknown::QueryInterface方法。插件则应当调用合适的接口的QueryInterface方法以确定驱动程序的支持接口版本并接收一个接口指针。


7.3.2创建插件
所有的打印机驱动程序插件必须定义DllMain,DllGetClassObject及DllCanUnloadNow函数。他们也必须实现IclassFactory COM接口及IPrintOemUI,IPrintOemUni或IPrintOemPS COM接口中之一。
当创建一个用户接口插件或者一个绘制插件,必须使代码基于这一DDK提供的UI插件的实例或绘制插件的实例。
定义一个DllMain函数(在平台的SDK文档中有描述),这是所有Win32 DLL的入口点。
定义并导出一个DllGetClassObject函数(在平台的SDK文档中有描述)。
打印机驱动程序调用这一函数以获得对插件实现的IClassFactory接口(在平台的SDK文档中有描述)的存取。当驱动程序调用DllGetClassObject,它指定下面一类的标识符(在prcomoem.h中定义)
CLSID_OEMNI——对UI插件
CLSID_OEMRENDER——对绘制插件
驱动程序也指定IID_IClassFactory的接口标识符。
DllGetClassObject函数必须创建一个它的IclassFactory接口的实例并为它返回一个指针,如在示例代码所示。
实现IClassFactory COM接口
IClassFactory接口的CreateInstance方法应当创建一个下面的COM接口的插件实现的实例:
IPrintOemUI COM接口
IPrintOemUni COM接口
IPrintOemPS COM接口
CreateInstance方法的一个输入是接口的标识符。驱动程序用IID_Iunknown的一个接口标识符调用CreateInstance,意思是CreateInstance方法必须为被创建的实例的IUnknown接口(在平台的SDK文档中描述)返回一个指针,如在示例代码中所示。
实现IPrintOemUI,IPrintOemUni或者IPrintOemPS COM接口中的一种,包括标准的IUnknown接口,如在例子代码中所示。
由驱动程序调用的第一个被实现的方法是IUnknown接口的QueryInterface方法(在平台SDK文档中有描述

)。这一方法为打印机以一个输入参数收到一个接口的标识符,驱动程序调用该方法以确定插件支持那一个版本的接口并收到指向支持接口的指针。
定义并导出DllCanUnloadNow函数(在平台的SDK文档中有描述)。
如果所有被实现的插件的IPrintOemUI,IPrintOemUni或者IPrintOemPS接口的实例已经被发布,DllCanUnloadNow函数必须返回S_OK,返回S_OK意指对驱动程序来说,插件不能被加载。


7.3.3从打印机驱动程序存取插件接口
如果一个UI插件或绘制插件已经被安装,打印机驱动程序(Unidrv或Pscript)将使用下面的调用序列以获取对插件的IPrintOemUI,IPrintOemUni或者IPrintOemPS接口的存取。
1.驱动程序调用LoadLibrary以加载插件的DLL,它引起插件的DllMain函数被调用。
2.驱动程序调用插件的DllGetClassObject函数,它返回一个指向插件的IDlassFactory接口的指针。
3.驱动程序调用IClassFactory接口的CreateInstance方法,指定一个IID_Unknown的接口标识符,它引起方法创建插件的IPrintOemUI,IPrintOemUni或者IPrintOemPS接口的实例并返回指向实例的IUnknown接口的指针。
4.驱动程序调用IUnknown接口的QueryInterface方法以确定插件支持IPrintOemUI,IPrintOemUni或者IPrintOemPS接口的那一版本,并接收一个指向支持接口的指针。
5.驱动程序调用插件的接口的PublishDriverInterface方法以使得驱动程序的IPrintOemUI,IPrintOemUni或者IPrintOemPS接口对插件可用。
6.如果插件已经实现了IPrintOemUni接口,驱动程序调用IPrintOemUni::GetImplementedMethod以确定哪一个接口方法已经被实现。


7.3.4从插件存取打印机驱动程序接口
如果一个插件能够调用属于驱动程序的IPrintOemUI,IPrintOemUni或者IPrintOemPS接口,它必须从驱动程序获得一个指针,如下:
1. 插件必须实现IPrintOemUI,IPrintOemUni或者IPrintOemPS接口的PublishDriverInterface方法。
2. 当驱动程序(Unidrv或Pscript)调用插件的PublishDriverInterface方法,它提供一个指向IPrintOemUI,IPrintOemUni或者IPrintOemPS实例的IUnknow接口。
3. 插件必须使用IUnknown接口指针去调用Iunknown::QueryInterface,指定表示是期望的版本的IPrintOemUI,IPrintOemUni或者IPrintOemPS接口的接口标识符(更多的信息,可参考打印机驱动程序的接口标识符部分)。
4. 如果插件指定一个接口的标识符表示一个驱动程序支持的接口,QueryInterface返回一个指向IPrintOemUI,IPrintOemUni或者IPrintOemPS接口的指针。注意,驱动程序在返回对插件的接口指针之前调用接口的AddRef方法(在平台的SDK文档中描述)。插件应当保存该指针,这样它可以在以后被用于调用接口方法。
5. 当IPrintOemUI,IPrintOemUni或者IPrintOemPS接口指针不再需要时,插件必须调用接口的Releas

e方法(在平台的SDK文档中有描述)。


7.4安装定制的驱动程序组件
当为微软打印机驱动程序提供定制的组件时,必须为组件的安装提供一个.ini文件(如果打印机不被ntprint.inf支持,必须提供一个printer.inf文件)。
.ini文件必须包含一个OEMFiles部分,在这一部分,每一个定制的组件是用下面之一的条目来描述的:


OEMDriverFilen
命名一个绘制插件


OEMConfigFilen
命名一个用户接口插件
这时,n指定了安装程序安装文件的顺序,对所有类型的插件来说,为n指定的数字必须是连续的,从1开始。
例如,如果提供两个绘制插件及一个用户接口插件,打印机模型是XYZ,.ini文件必须如下所示:
[OEMFiles]
OEMDriverFile1=XYZDRV1.DLL
OEMConfigFile1=XYZUI1.DLL
OEMDriverFile2=XYZDRV2.DLL
在等号(=)之前或之后,都不允许有空格,文件名不能名含路径说明。
在例子中,指定了两个绘制插件,基于为OEMDriverFilen指定的n值。xyzdrv1.dll在xyzdrv2.dll之前被安装。Unidrv及Pscript驱动程序调用插件,并按其安装的顺序,此后,当一个驱动程序需要调用DDI分出函数及由这些插件提供的COM方法时,xyzdrv1.dll将在xyzdrv2.dll之前被调用。
.ini文件名应当反映打印机产品名称并且是唯一的以避免在.ini文件中与其他打印机名称相冲突。注意如果提供一个与Windows NT 4.0后端口(Back-Porting)通信的绘制插件或用户接口插件。.ini文件名必须与.gpd及.ppd文件匹配。(即xyz.ini必须用于xyz.gpd或xyz.ppd)。这一限制对Windows 2000及以后版本不适用。
一个.ini文件可以包含ANSI或UNICODE文本,但是推荐使用UNICODE文本。在一个.ini文件中,每行以#开始的是注解的内容。
更多的关于.inf及.ini文件的信息,参考Windows 2000驱动程序开发指南中的第一卷,即插即用,电源管理及建立设计指南部分。也可参考第4章微软统一打印机驱动程序中的安装一个Unidrv小驱动程序部分。


7.4.1Unidrv的定制的字体安装程序
对没有在打印机的GPD文件中通过字体Cartridge条目描述的Cartridge字体,需要厂商提供的字体安装程序软件。这些字体需要用Unidrv字体格式文件(.uff文件)来描述,而厂商提供的字体安装程序就负责创建.uff文件。
厂商提供的字体安装程序应当提供对下载的PCL软字体的支持。
下面两种技能为创建定制的安装程序提供:
提供一个用户接口插件
插件必须实现下面的COM接口方法:
IPrintOemUI::FontInstallerDlgProc
IPrintOemUI::UpdateExternalFonts
提供一个单独的执行文件
在字体安装时,可执行文件必须通过调用SetPrinterData(在平台的SDK文档中描述)存储它的名字在注册表中,并为“FontInstaller”关键字指定一个值。
Unidrv用下面的算法定位

字体安装程序:
1.如果字体安装程序可执行文件的名字被存储于注册表中,Unidrv不允许系统管理员从打印机的属性表单中选择字体安装程序。相反,管理员必须运行提供的可执行文件。
2.如果一个安装程序执行文件不可用,Unidrv允许从打印机的属性表单中选择字体安装操作。Unidrv确定是否一个用户接口插件已经被安装。如果是,它的字体安装方法被调用。如果一个用户接口插件没有被安装,或者它的字体安装方法返回了E_NOTIMPL,则驱动程序使用它自已的容错安装程序。

相关文档
相关文档 最新文档