鸿 网 互 联 www.68idc.cn

虚拟打印的实现-SPL转换成EMF推荐

来源:互联网 作者:佚名 时间:2018-02-25 10:27
上次写到如何编写一个虚拟打印机的驱动部分。系统在打印一个任务时是先将这个任务生成为一个SPL文件,然后才发送给打印机。我们可以使用上次写的DLL程序,将系统生成SPL文件,在还没有发送给打印机的时候,将这个SPL文件转换成一个EMF文件。一旦生成了EMF文件
上次写到如何编写一个虚拟打印机的驱动部分。系统在打印一个任务时是先将这个任务生成为一个SPL文件,然后才发送给打印机。我们可以使用上次写的DLL程序,将系统生成SPL文件,在还没有发送给打印机的时候,将这个SPL文件转换成一个EMF文件。一旦生成了EMF文件以后,我们就可以随意的将它转换成任意的格式。下面的代码的功能就是将一个SPL文件转换成一个EMF文件。   function SPLToEMF(): Boolean;stdcall;export;//将SPL类型转换为EMF文件   reg  : TRegistry;   SearchRes : TSearchRec;// 查找文件的结构   nGaugeCounter,  // makes nice gauge   nFound, i : Integer;  // # of files found (when searching)   strTemp : string[8];  // filename: number .emf   strCnt : string;  // full path + emf-file   strSpoolDir : string;  // spool-directory (NT only)   strOldFile, strNewFile : string; // filename (NT: spool file)   m_strTempVar : string; // registry entry holding destination dir for print jobs   strDestDir : string;  // 保存EMF文件的路径   strSHDFile : string;  // instruction file   lpszTempDir : PChar;  // %TEMP%的路径名称(仅用于95 or NT)%TEMP% dir (w95 nt)   lpszSpoolDir : PChar;  // 打印处理器的路径名称(仅用于NT or 2K)spool dir (nt only)   IsEnd:Boolean;   label Res;  // 定义返回的goto变量   begin   IsEnd:=false;   nGaugeCounter := 0;   //初始化lpszTempDir和lpszSpoolDir   GetMem(lpszTempDir, 255);   GetMem(lpszSpoolDir, 255);   if (GetEnvironmentVariable('temp', lpszTempDir, 255) = 0) then   begin   MsgError('Environment Variable %temp% not set!' + #13 +   'Either install driver properly or' + #13 + 'define a %temp% environment variable.');   FreeMem(lpszTempDir);   goto Res;   end;   strTempDir := string(lpszTempDir);   FreeMem(lpszTempDir);   //从注册表中得到EMF文件的目的路径   reg:=TRegistry.Create;   reg.RootKey:=HKEY_LOCAL_MACHINE;   if reg.OpenKey(PMON_KEY,TRUE) then   begin   m_strTempVar := reg.ReadString('Temp');   end;   reg.CloseKey;   reg.Free;   if (m_strTempVar = '') then   begin   strTempDir:='C:\TEMP';   MsgError('您的打印目的没有选择,文件将保存在C:\TEMP下');   end   else   begin   strTempDir := m_strTempVar;   end;   if (strTempDir[Length(strTempDir)] '\') then   begin   strTempDir := Concat(strTempDir, '\');   end;   nFileCounter := 1;   //得到系统版本   strOSVer := GetOSName;   //根据版本处理   {对于NT 和其高版本的操作系统}   if (strOSVer = 'Windows NT') or (strOSVer = 'Windows 2000') or (strOSVer = 'Windows XP') then   begin   //得到spool的路径   GetEnvironmentVariable('windir', lpszSpoolDir, 255);   strSpoolDir := string(lpszSpoolDir) + '\system32\spool\PRINTERS\';   FreeMem(lpszSpoolDir);   end;   //在临时文件夹中删除旧的emf文件和spl文件   nFound := FindFirst(strTempDir + '*.emf', faAnyFile, SearchRes);   while nFound = 0 do   begin   DeleteFile(PChar(strTempDir + SearchRes.Name));   nFound := FindNext(SearchRes);   end;   FindClose(SearchRes);   {对于NT以下的操作系统}   if (strOSVer = 'Windows 95') or (strOSVer = 'Windows98') or (strOSVer = 'Windows 98SE') or (strOSVer = 'Windows ME') then   begin   MsgError('此虚拟打印暂时不支持低版本系统。');   end   else   begin   StringList := TStringList.Create;   //在打印机的临时文件夹中查找临时文件   nFound := FindFirst(strSpoolDir + '*.SPL', faAnyFile, SearchRes);   while nFound = 0 do   begin   Inc(nGaugeCounter);   nFound := FindNext(SearchRes);   end;   FindClose(SearchRes);   nFileCounter := 0;   nFound := FindFirst(strSpoolDir+ '*.SPL', faAnyFile, SearchRes);   if nFound = 0 then   begin   {$I-}   DateSeparator := '-';   TimeSeparator := '-';   //重新编写EMF的目的路径   strDestDir := strTempDir;   //创建文件夹   if IOResult 0 then   begin   raise Exception.Create('不能创建文件夹 ' + strDestDir + ': ' + IntToStr(IOResult))   end;   end;   while nFound = 0 do   begin   strOldFile := strSpoolDir + SearchRes.Name;   strSHDFile := StringReplace(strOldFile, '.SPL', '.SHD', [rfIgnoreCase]);   strNewFile := strDestDir + '\' + SearchRes.Name;   StringList.Add(strNewFile);   if not FileExists(strOldFile) then   begin   raise Exception.Create('SPOOL文件没有找到: ' + strOldFile)   end   else   begin   if not CopyFile(PChar(strOldFile), PChar(strNewFile), False) then   begin   raise Exception.Create('不能拷贝文件: ' + strOldFile);   end;   end;   nFound := FindNext(SearchRes);   Inc(nFileCounter);   strCnt := '';   strTemp := '';   end;   FindClose(SearchRes);   for i:=0 to nFileCounter-1 do   begin   ReadBinaryDataFile(StringList.Strings[i], strDestDir + '\');   end;   end;   nFound := FindFirst(strSpoolDir + '*.spl', faAnyFile, SearchRes);   while nFound = 0 do   begin   DeleteFile(PChar(strSpoolDir + SearchRes.Name));   nFound := FindNext(SearchRes);   end;   FindClose(SearchRes);     nFound := FindFirst(strSpoolDir + '*.shd', faAnyFile, SearchRes);   while nFound = 0 do   begin   DeleteFile(PChar(strSpoolDir + SearchRes.Name));   nFound := FindNext(SearchRes);   end;   FindClose(SearchRes);   IsEnd:=true;   Result:=IsEnd;       上面的函数中使用到的一些结构EMFheader结构如下定义 type EMFheader = record   Signature: Integer;   EMFsize: Integer;   end;   const EMFheaderSignature = $0C;   使用到的ReadBinaryDataFile函数如下实现。   //读出一个NT下的 *.spl文件并将其转换为一个*.EMF文件 //参数说明 strFilename:*.spl文件的文件名称 strDestDir需要转换成为*.emf文件的文件明成 procedure ReadBinaryDataFile(strFilename : string; strDestDir : string);   fFromF, fToF  : file;  //定义输入和输出文件   strEMFFileName, strTmp : string;   nRead, nWritten, i, nReadTotal, nNextFilePos : Integer;   Buf  : array[1..2048] of Char; //定义一个读取EMF文件的buffer   nPixFound, test  : Integer;   PosList  : TStringList;   strHeaderBytes  : string; //从函数fDetectHeaderBytes读出的6字节长的emf文件头 begin   if not FileExists(strFileName) then   begin   raise Exception.Create('不能读文件: ' + strFileName)   end   else   begin   strHeaderBytes := fDetectHeaderBytes(strFileName);   AssignFile(fFromF, strFileName);   end;   Reset(fFromF, 1);   PosList := TStringList.Create;   nPixFound := 0;   nReadTotal := 0;   repeat   //注意strHeaderBytes的含义   BlockRead(fFromF, Buf, SizeOf(Buf), nRead);   test := Pos(strHeaderBytes, Buf);   if (test 0) then   begin   Inc(nPixFound);   if test 0 then PosList.Add(IntToStr(test + nReadTotal));   end;   Inc(nReadTotal, nRead);   until (nRead = 0) ;   for i:=1 to nPixFound do   begin   strTmp := IntToStr(i);   while Length(strTmp) 8 do   begin   Insert('0', strTmp, 1);   end;   strEMFFileName := Concat(strDestDir, strTmp,'.EMF');   AssignFile(fToF, strEMFFileName);   Rewrite(fToF, 1);   try   Seek(fFromf, StrToInt(PosList.Strings[i-1])-1);   repeat   BlockRead(fFromF, Buf, SizeOf(Buf), nRead);   BlockWrite(fToF, Buf, nRead, nWritten);   if i nPixFound then   nNextFilePos := StrToInt(PosList.Strings[i])   else   nNextFilePos := FileSize(fFromF);   until (FilePos(fFromF) =nNextFilePos);   except   on EInOutError do MsgError('读文件错误');   end;   CloseFile(fToF);   end;  CloseFile(fFromF);   PosList.Free;   DeleteFile(strFilename);   上面的代码希望对大家有所帮助,下次我将会把我的代码中如何将一个EMF文件转换成一个BMP文件贴出。  
网友评论
<