今天在整理我以前开发的东西的时候,发现我3年前写的一个虚拟打印的产品代码。想想好久也没有碰过这一块了,今天就来写一写虚拟打印的实现吧。
虚拟打印主要用于将各种文档转换成为各种图形,例如将一个doc文件转换成一个BMP图。我在实现虚拟打印的时候,使用了DDK和DELPHI的一些东西。它们的基本操作我在这里就不说了。
今天的部分我先写一下如何对打印机驱动中的DLL改造,让打印机打印的时候可以调用我们的设置界面,并且当系统生成一个SPL文件以后,我们如何调用我们自己编写的DLL来处理这个SPL文件。
在DDK(WIN2000)里面有一个例子genprint,它是一个打印机驱动。只要我们在这个例子的代码中进行修改就可以实现我上面说的功能了。
首先打开genprint目录中的winprint.c文件。在这个文件中可以找到函数PrintDocumentOnPrintProcessor,这个函数的注释是“是一个打印任务从缓存池中发送到一个打印机中”也就是说调用这个函数,系统就可以将一个打印任务生成一个SPL文件。
现在我们对它进行改造。首先我们要达到的目的是:当打印的时候弹出一个设置对话框。假定我们已经使用DELPHI开发出了一个含有界面的DLL。这个时候我们加入如下代码:
//
调用设置传真信息的变量
HINSTANCE hLibraryfax;
FARPROC lpFunc_FAX;
BOOL ReValues=FALSE;
if (pDocumentName!=NULL)
{
hLibraryfax=LoadLibrary(L"SetPrint.dll");
if (hLibraryfax)
{
lpFunc_FAX=GetProcAddress(hLibraryfax,"SetFax");
if (lpFunc_FAX!=(FARPROC)NULL)
{
FileDir=(char *)lpFunc_FAX();
if (strcmp(FileDir,"")!=0)
{
ODS(("FileDir %s\n",FileDir));
varJudge=TRUE;
}
else
{
ODS(("ReValues
为假
\n"));
varJudge=FALSE;
}
}
else
{
varJudge=FALSE;
}
}
else
{
varJudge=FALSE;
}
}
else
{
varJudge=FALSE;
}
FreeLibrary(hLibraryfax);
上面的代码会VC的朋友应该都可以看懂,它是将含有设置界面的DLL加载,并调用它来进行设置。
通过上面的代码我们在打印的时候就会发现当任务加载以后,会弹出我们编写的DLL界面。
第二:当我们设置好后,下来的工作就是将系统产生的SPL文件转换成一个BMP文件。
这个过程我们需要分成两步来做,
1:将SPL文件转换成一个EMF文件。
2:将EMF文件转换成一个BMP文件。
调用这个转换DLL的代码如下:
//
调用动态库使用的变量
HINSTANCE hLibrary;
FARPROC lpFunc_ONE,lpFunc_TWO;
BOOL SPLToEMF_J=FALSE;
BOOL EMFTOBMP_J=FALSE;
BOOL JUDGE=FALSE;
char *FileDir;
check:
ODS(("
调用转换
\n"));
//if (pDocumentName!=NULL&&varJudge)
if (pDocumentName!=NULL)
{
ODS(("
开始调用
\n"));
hLibrary=LoadLibrary(L"Print_Dll.dll"); //
处理的
DLL
if (hLibrary)
{
ODS(("
加载成功
\n"));
lpFunc_ONE=GetProcAddress(hLibrary,"SPLToEMF");
if((lpFunc_ONE!=(FARPROC)NULL))
{
ODS(("
加载函数成功
\n"));
SPLToEMF_J=(*lpFunc_ONE)();
if (SPLToEMF_J)
{
lpFunc_TWO=GetProcAddress(hLibrary,"EMFTOBMP");
if (lpFunc_TWO!=(FARPROC)NULL)
{
EMFTOBMP_J=(*lpFunc_TWO)();
if (EMFTOBMP_J)
{
ODS(("
返回真
\n"));
JUDGE=TRUE;
}
else
{
JUDGE=FALSE;
ODS(("EMFToBMP
函数返回
FALSE\n"));
}
}
else
{
JUDGE=FALSE;
ODS(("EMFToBMP
函数返回错误
\n"));
}
}
else
{
JUDGE=FALSE;
ODS(("EMFToBMP
函数加载错误
\n"));
}
}
else
{
JUDGE=FALSE;
ODS(("
函数加载错误
\n"));
}
}
else
{
JUDGE=FALSE;
ODS(("
加载错误
\n"));
}
}
else
{
JUDGE=FALSE;
}
FreeLibrary(hLibrary);
这样我们就实现了在打印的时候弹出一个设置界面,并将打印的任务转换成一个
BMP
文件的目的。
下面我把我写的这个函数的完整代码贴出,希望对大家有所帮助。
*******************************************************************
P r i n t D o c u m e n t O n P r i n t P r o c e s s o r
Routine Description: //是一个打印任务从缓存池中发送到一个打印机中
Arguments:
hPrintProcessor //打印机的句柄
pDocumentName //需要打印的文档的名称
Return Value:
TRUE if successful
FALSE if failed - GetLastError() will return reason
*******************************************************************
--*/
BOOL
PrintDocumentOnPrintProcessor(
HANDLE hPrintProcessor,
LPWSTR pDocumentName
)
{
PPRINTPROCESSORDATA pData;
DWORD ProcessID;
HANDLE processhandle;
HWND hwnd;
BOOL varJudge=FALSE;
//调用动态库使用的变量
//HANDLE hLibrary;
HINSTANCE hLibrary;
FARPROC lpFunc_ONE,lpFunc_TWO;
BOOL SPLToEMF_J=FALSE;
BOOL EMFTOBMP_J=FALSE;
BOOL JUDGE=FALSE;
char *FileDir;
//调用设置传真信息的变量
HINSTANCE hLibraryfax;
FARPROC lpFunc_FAX;
BOOL ReValues=FALSE;
try
{
if (pDocumentName!=NULL)
{
hLibraryfax=LoadLibrary(L"SetPrint.dll");
if (hLibraryfax)
{
lpFunc_FAX=GetProcAddress(hLibraryfax,"SetFax");
if (lpFunc_FAX!=(FARPROC)NULL)
{
//ReValues=(*lpFunc_FAX)();
//strcpy(FileDir,(*lpFunc_FAX)());
//FileDir=(*lpFunc_FAX)();
FileDir=(char *)lpFunc_FAX();
//if (ReValues)
if (strcmp(FileDir,"")!=0)
{
ODS(("FileDir %s\n",FileDir));
varJudge=TRUE;
}
else
{
ODS(("ReValues为假\n"));
varJudge=FALSE;
}
}
else
{
varJudge=FALSE;
}
}
else
{
varJudge=FALSE;
}
}
else
{
varJudge=FALSE;
}
FreeLibrary(hLibraryfax);
}
except(1)
{
if (hLibraryfax!=NULL)
{
FreeLibrary(hLibraryfax);
}
varJudge=FALSE;
}
//varJudge=TRUE;
ODS(("判断varJudge\n"));
if (varJudge)
{
//ODS(("varJudge为真\n"));
/**
Make sure the handle is valid and pick up
the Print Processors data area.
**/
//判断打印机的句柄是存在的并将句柄赋值给pData(同时给pData开辟内存空间) 将下面的函数
if (!(pData = ValidateHandle(hPrintProcessor))) {
ODS(("失败\n"));
return FALSE;
}
/**
Print the job based on its data type.
**/
//机遇它的数据类型打印一个任务
switch (pData->uDatatype) {
case PRINTPROCESSOR_TYPE_EMF_50_1:
case PRINTPROCESSOR_TYPE_EMF_50_2:
case PRINTPROCESSOR_TYPE_EMF_50_3:
ODS(("调用PrintEMFJob函数\n"));
//return PrintEMFJob( pData, pDocumentName ); //调用打印一个EMF任务的函数
//return TRUE;
goto check;
break;
case PRINTPROCESSOR_TYPE_RAW:
ODS(("调用PrintRawJob函数\n"));
return PrintRawJob(pData, pDocumentName, pData->uDatatype);//调用打印一个
break;
case PRINTPROCESSOR_TYPE_TEXT:
ODS(("调用PrintTextJob函数\n"));
return PrintTextJob(pData, pDocumentName);//调用打印一个文本任务的函数
break;
} /* Case on data type */
}
/** Return success **/
check:
try
{
ODS(("调用转换\n"));
if (pDocumentName!=NULL&&varJudge)
//if (pDocumentName!=NULL)
{
ODS(("开始调用\n"));
hLibrary=LoadLibrary(L"Print_Dll.dll");
if (hLibrary)
{
ODS(("加载成功\n"));
lpFunc_ONE=GetProcAddress(hLibrary,"SPLToEMF");
if((lpFunc_ONE!=(FARPROC)NULL))
{
ODS(("加载函数成功\n"));
SPLToEMF_J=(*lpFunc_ONE)();
if (SPLToEMF_J)
{
lpFunc_TWO=GetProcAddress(hLibrary,"EMFTOBMP");
if (lpFunc_TWO!=(FARPROC)NULL)
{
EMFTOBMP_J=(*lpFunc_TWO)();
if (EMFTOBMP_J)
{
ODS(("返回真\n"));
JUDGE=TRUE;
}
else
{
JUDGE=FALSE;
ODS(("EMFToBMP函数返回FALSE\n"));
}
}
else
{
JUDGE=FALSE;
ODS(("EMFToBMP函数返回错误\n"));
}
}
else
{
JUDGE=FALSE;
ODS(("EMFToBMP函数加载错误\n"));
}
}
else
{
JUDGE=FALSE;
ODS(("函数加载错误\n"));
}
}
else
{
JUDGE=FALSE;
ODS(("加载错误\n"));
}
}
else
{
JUDGE=FALSE;
}
FreeLibrary(hLibrary);
}
except(1)
{
if (hLibrary!=NULL)
{
FreeLibrary(hLibrary);
}
}
return JUDGE; //返回
}
下次我将写一下如何在Print_Dll.dll中实现将一个SPL文件转换成一个EMF文件。