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

本文介绍了一种方法,能够将打印任务生成的SPL文件转换为EMF格式,并提供了详细的代码实现。通过该方法,可以进一步将EMF文件转换为其他格式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上次写到如何编写一个虚拟打印机的驱动部分。系统在打印一个任务时是先将这个任务生成为一个SPL文件,然后才发送给打印机。我们可以使用上次写的DLL程序,将系统生成SPL文件,在还没有发送给打印机的时候,将这个SPL文件转换成一个EMF文件。一旦生成了EMF文件以后,我们就可以随意的将它转换成任意的格式。下面的代码的功能就是将一个SPL文件转换成一个EMF文件。
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

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;

  //初始化lpszTempDirlpszSpoolDir

  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文件贴出。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值