Как прочитать SPL файл ?

SPL файл - временный файл создаваемый при печати операционными системами Windows 2x, WindowsXP, Wista. Его чтение необходимо для мониторинга работы принтера. SPL файл создаётся с момента формирования задания принтера и удаляется когда печать задания завершена. Когда задание полностью сформировано в паре с SPL файлом создаётся файл с расширением SHD. SPL и SHD файлы создаются в каталоге %windir%\system32\spool\PRINTERS\. После окончания печати задания SPL и SHD файлы удаляются. Поэтому до окончания задания SPL файл необходимо скопировать для дальнейшего чтения. Это возможно сделать по какому-либо событию принтера, например, PRINTER_CHANGE_JOB, хотя можно выбрать и другое событие принтера. Чтение SPL файла производится побайтно. Структура файла SPL файла сильно зависит от используемого драйвера принтера. Поэтому, нижеприведенный алгоритм чтения подходит не ко всем случаям. SPL файл состоит из набора записей. Каждая запись состоит из 3-х полей : тип записи, длина записи, содержимое записи. Как правило, запись с типом 1 завершает SPL файл, а запись 12 содержит печатаемую страницу в EMF виде. Записей под номером 12 может быть несколько в SPL файле в соответствии с количеством страниц в печатаемом файле. Фрагмент Delphi программы показывает как реализовано чтение 12 записи с последующим отображением в компоненте Image: procedure TForm1.Button3Click(Sender: TObject); label g2; var f2:file; iType2, nSize2 : DWORD; nRead2, henh2, pcount2 : integer; Para2 : array [1..16832] of DWORD; bits2 : pointer; Mfile2 : tmetafile; Mfilecanvas2 : tmetafilecanvas; goodnews :boolean; begin pcount2:=1; if Listbox1.ItemIndex<0 then goto g2; goodnews:=false; AssignFile(f2,ProgDir+ListBox1.Items.Strings[Listbox1.ItemIndex]); Reset(f2,1); BlockRead(f2,iType2,4,nRead2); BlockRead(f2,nSize2,4,nRead2); if (nSize2>0) then BlockRead(f2,Para2,(nSize2-8),nRead2); while not EOF(f2) do begin BlockRead(f2,iType2,4,nRead2); BlockRead(f2,nSize2,4,nRead2); if (iType2=1) then break; if ((iType2=12)and((page)<pcount2)) then begin goodnews:=true;break;end; if (iType2=12) then pcount2:=pcount2+1; if (iType2<65535) then BlockRead(f2,Para2,(nSize2),nRead2); end; if goodnews then begin getmem(bits2,nSize2); BlockRead(f2,bits2^,nSize2); CloseFile(f2); henh2:=SetEnhMetaFileBits(nSize2,bits2); Mfile2:=TMetaFile.Create; Mfile2.Width:=Printer.PageWidth; Mfile2.Height:=printer.PageHeight; MfileCanvas2:=TMetafileCanvas.Create(Mfile2, 0); playenhmetafile(MfileCanvas2.Handle ,henh2, Rect(0,0,Printer.PageWidth,printer.PageHeight)); DeleteEnhMetaFile(henh2); MFileCanvas2.Free; freemem(bits2,nSize2); deletefile(ProgDir+'Meta.emf'); MFile2.SaveToFile(ProgDir+'Meta.emf'); Mfile2.Free; page := pcount2; end else begin CloseFile(f2);end; Image1.Picture.LoadFromFile(ProgDir+'Meta.emf'); g2:end; Первые два оператора BlockRead читают тип и размер первой записи, а третий оператор BlockRead(f2,Para2,(nSize2-8),nRead2) считывает содержимое записи уменьшенное на 8. Такой странный способ чтения используется только для первой записи. Далее количество байт считываемого содержимого записи совпадает с её размером.
© Yalta2006