iniwf

风是温柔的,雨是伤心的,云是快乐的,月是多情的,爱是迷失的,恋是醉人的,情是难忘的,天是长久的,地是永恒的

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

转自http://fxh7622.blog.51cto.com/63841/48833

上次写到如何编写一个虚拟打印机的驱动部分。系统在打印一个任务时是先将这个任务生成为一个SPL文件,然后才发送给打印机。我们可以使用上次写的DLL程序,将系统生成SPL文件,在还没有发送给打印机的时候,将这个SPL文件转换成一个EMF文件。一旦生成了EMF文件以后,我们就可以随意的将它转换成任意的格式。下面的代码的功能就是将一个SPL文件转换成一个EMF文件。
 
function SPLToEMF(): Boolean;stdcall;export;
//将SPL类型转换为EMF文件
var
  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;
Res:
  Result:
=IsEnd;
end;
 
 
 
上面的函数中使用到的一些结构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);
var
  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);
end;
 
上面的代码希望对大家有所帮助,下次我将会把我的代码中如何将一个EMF文件转换成一个BMP文件贴出。
 
本文出自 “狗窝” 博客,请务必保留此出处http:
//fxh7622.blog.51cto.com/63841/48833

本文出自 51CTO.COM技术博客 


posted on 2009-03-18 15:04 iniwf 阅读(1784) 评论(0)  编辑 收藏 引用 所属分类: 驱动


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

统计

常用链接

留言簿(2)

随笔分类

随笔档案

收藏夹

IT技术

积分与排名

最新评论

阅读排行榜

评论排行榜