Autor Beitrag
SchelmVomElm
ontopic starontopic starontopic starontopic starontopic starofftopic starofftopic starofftopic star
Beiträge: 154

W2K Pro
D5 Pro
BeitragVerfasst: Do 31.03.05 10:00 
Moin allerseits!

Dieses Tutorial bezieht sich auf die Erstellung von Pdf Dateien mit Ghostscript & Co.
Um es gleich vorweg zu nehmen:

Nein, ich kenne keine Möglichkeit Pdfs ohne GS zu erstellen.

Es gibt noch die Möglichkeit Pdfs mit freien Komponenten zu erstellen (Nishita usw.) die sind aber so einfach gestrickt, dass sie meiner Erfahrung nach nicht einmal für den Hausgebrauch reichen. Anders sieht es mit den kostenpflichtigen Komponenten wie WPDF o.ä aus. Aber die kosten halt Geld...

1. Was braucht man?

- Ghostscript muss installiert sein. (unumgänglich)
- FreePdf (es gibt auch einen Weg das direkt mit GS zu machen –
ich krieg es bloss nicht hin – mehr dazu später...
- Einen installierten PostScript Drucker.
- Die Delphi Quelle von TPrinter.

2. Post Script Dateien erzeugen

Die Idee ist eine PostScript Datei zu erzeugen und die mit FreePdf bzw. GS zu destillieren.
Dazu muss man erstmal einen Weg finden direkt in eine PS Datei zu drucken ohne dass der Drucker Dialog aufgeht und einem nach einem Speicherort fragt. Die Lösung findet sich hier im Forum und stammt von Tino. Leider muss hierfür die Quelle von TPrinter erweitert werden:

www.delphi-forum.de/viewtopic.php?t=11003

1. Ein weiteres Property dem tPrinter Objekt hinzufügen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
private 
  fOutputFile: String 
Public 
  Property OutputFile: String read fOutputFile write fOutputFile;


2. In der Procedure BeginDoc werden dem DocInfo-Record einige Werte zugewiesen. Dort wird das o. g. neue Property hinzugefügt:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
with DocInfo do 
  begin 
    cbSize := SizeOf(DocInfo); 
    lpszDocName := PChar(Title); 
    lpszOutput := PChar(fOutputFile);  // NEU 
  end;


So, nun kann man direkt in eine Datei drucken und wenn man einen PS Drucker installiert hat sind die Dateien auch von GS destillierbar! Ein geeigneter Drucker ist z.B.
Apple LaserWriter II NT v47.0. An dieser Stelle wäre es schön zu wissen wie man einen Drucker automatisch installiert oder noch besser wie man ihn temporär installiert. Wenn mir das jemand verraten könnte wäre ich SEHR DANKBAR!

So erzeugt man dann eine PS Datei:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
function CreatePS(const psPath, psPrinter: string): boolean;
var i: integer;
begin
  Result := true;
  try
    with Printer do
    begin
      for i:=0 to Printers.Count -1 do
        if Printers[i] = psPrinter then
        begin
          PrinterIndex := i;
          break;
        end;
      OutputFile:= psPath;
      BeginDoc;
      //Nun darf gezeichnet werden...
      Canvas.Malwas...
      Canvas.Schreibwas...
      Canvas.blabla...
      EndDoc;
    end;
  except
    Result := false;
  end;
end;


3. PS Datei destillieren

Nun ist die PS Datei vorhanden und muss noch von GS destilliert werden. GS hat dafür eigentlich Batchdateien z.B. ps2pdf.bat - leider bin ich zu blöd die zu benutzen. Wenn jemand weiß wie das geht – immer her damit!
Na ja, da ich offensichtlich zu blöd bin (oder mein GS nicht richtig installiert ist?) habe ich es dann mit FreePdf gelöst:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
procedure Distill(psPath: string);
var
  SInfo: TStartupInfo;
  PInfo: TProcessInformation;
  Reg: TRegistry;
  Cmd, fpPath: string;
begin
  //Pfad von FreePdf finden
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_LOCAL_MACHINE;
  Reg.OpenKey('\Software\shbox\FreePdfXP',False);
  fpPath := Reg.ReadString('fpDir');
  fpPath := fpPath + 'freepdf.exe';
  Reg.Free;
  //Kommandozeile zusammenbasteln
  Cmd := '"' + fpPath + '" ' + psPath + ' /a /x';
  //Auf das fertig Destillieren warten
  FillChar(SInfo, SizeOf(SInfo), #0);
  with SInfo do
  begin
   cb := SizeOf(SInfo);
   dwFlags := STARTF_USESHOWWINDOW;
   wShowWindow := SW_HIDE;
  end;
  if CreateProcess(nil, PChar(Cmd), nilnil, false, CREATE_NEW_CONSOLE or
  NORMAL_PRIORITY_CLASS, nil, PChar(ExtractFilePath(fpPath)), SInfo,PInfo) then
    WaitForSingleObject(PInfo.hProcess, INFINITE);
  //Ps - Datei löschen
  DeleteFile(psPath);
end;


FreePdf erzeugt in dem Beispiel eine Pdf- Datei in dem Verzeichnis in dem die PS- Datei steht mit dem Namen der PS- Datei – also aus C:\Test.ps wird C:\Test.pdf

So viel dazu. Ich hoffe, dass der ein oder andere noch Ideen hat wie man das ganze optimieren könnte.

MfG Schelm

_________________
for(;P("\n"),R--;P("|"))for(e=C;e--;P("_"+(*u++/8)%2))P("|"+(*u/4)%2);