Delphi: How to print a PDF without showing it?

37,509

Solution 1

There are some different possibilities to print PDFs... it depends whether you can require Adobe Reader to be installed (I don't know if you want to distribute your tool or just use it yourself).

1) It is possible to load the ActiveX control of Adobe Reader and use it for printing

pdfFile.src := 'filename.pdf'; 
pdfFile.LoadFile('filename.pdf'); 
pdfFile.print;

2) You can print PDFs with Adobe Reader itself (could be done with FoxIt too)

ShellExecute(0, 'open', 'acrord32', PChar('/p /h ' + FileName), nil, SW_HIDE);

3) You could also use Ghostview and Ghostprint

ShellExecute(Handle, 'open', 'gsprint.exe', PChar('"' + filename + '"'), '', SW_HIDE);

4) Or you could use a third party library... There are some available, but not all of them are free

Solution 2

Here are a bunch of routines I have written in my libary. If you pass a pdf file as parameter to PrintUsingShell it should print if a Acrobat reader program has been installed (might work with other pdf-software too if they registered themselfs in the registry).

  PrintUsingShell( x );


  procedure PrintUsingShell( psFileName :string);
  var s : string;
      i : integer;
  begin
     if not FileExists(psFileName)
     then
        Exit;

     s := FindShellPrintCmd( ExtractFileExt(psFileName) );
     i := Pos('%1',s);
     if i > 0
     then begin
        System.Delete(s,i,2);
        System.Insert(psFileName,s,i);
        Execute(s);
     end;
  end;

  function FindShellCmd(psExtension:string;psCmd:string): string;
  var r : TRegistry;
      sName : string;
  begin
     psExtension := Trim(psExtension);
     if psExtension = ''
     then begin
        Result := '';
        Exit;
     end;

     psCmd := Trim(psCmd);
     if psCmd = ''
     then
        psCmd := 'OPEN'
     else
        psCmd := UpperCase(psCmd);

     if psExtension[1] <> '.'
     then
        psExtension := '.' + psExtension;

     r := TRegistry.Create(KEY_READ);
     try
        r.RootKey := HKEY_LOCAL_MACHINE;
        r.OpenKeyReadOnly('software\classes\' + psExtension);
        sName := r.ReadString('');
        r.CloseKey();

        r.OpenKeyReadOnly('software\classes\' + sName + '\Shell\' + psCmd + '\Command');
        Result := r.ReadString('');
        r.CloseKey();
     finally
        FreeAndNil(r);
     end;
  end;
  function FindShellOpenCmd(psExtension:string):string;
  begin
     Result := FindShellCmd(psExtension,'OPEN');
  end;

  function FindShellPrintCmd(psExtension:string):string;
  begin
     Result := FindShellCmd(psExtension,'PRINT');
  end;

  {$ifdef windows}
  function LocalExecute( psExeName:string ; wait:boolean ; how:word):word;
  var i : integer;
      prog,parm:string;
      msg:TMsg;
      rc : word;
  begin

     i := pos(psExeName,' ');
     if i = 0
     then begin
        prog := psExeName;
        parm := '';
     end
     else begin
        prog := copy( psExeName,1,i-1);
        parm := copy( psExeName,i+1,255);
     end;

     if pos(prog,'.') <> 0
     then
        prog := prog + '.exe';

     psExeName := prog + ' ' + parm + #0;

     rc := WinExec( @psExeName[1] , how );
     if wait
     then begin
        if (rc > 32)
        then begin
           repeat
              if PeekMessage(Msg,0,0,0,PM_REMOVE)
              then begin
                 TranslateMessage(Msg);
                 DispatchMessage(Msg);
              end;
           until (GetModuleUsage(rc) = 0)
        end;
     end;
  end;   { LocalExecute }
  {$endif}
  {$ifdef win32}
  function LocalExecute32(FileName:String; Wait:boolean; Visibility : integer;
                          lWaitFor:Cardinal=INFINITE):integer;
  var zAppName:array[0..512] of char;
      zCurDir:array[0..255] of char;
      WorkDir:String;
      StartupInfo:TStartupInfo;
      ProcessInfo:TProcessInformation;
  begin
     StrPCopy(zAppName,FileName);
     GetDir(0,WorkDir);
     StrPCopy(zCurDir,WorkDir);
     FillChar(StartupInfo,Sizeof(StartupInfo),#0);
     StartupInfo.cb := Sizeof(StartupInfo);
     StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
     StartupInfo.wShowWindow := Visibility;
     if not CreateProcess(nil,
        zAppName,                      { pointer to command line string }
        nil,                           { pointer to process security attributes }
        nil,                           { pointer to thread security attributes }
        false,                         { handle inheritance flag }
        CREATE_NEW_CONSOLE or          { creation flags }
        NORMAL_PRIORITY_CLASS,
        nil,                           { pointer to new environment block }
        nil,                           { pointer to current directory name }
        StartupInfo,                   { pointer to STARTUPINFO }
        ProcessInfo)                   { pointer to PROCESS_INF }
     then Result := -1
     else begin
        if Wait
        then begin
           Result := WaitforSingleObject(ProcessInfo.hProcess,lWaitFor);
           GetExitCodeProcess(ProcessInfo.hProcess,LongWord(Result));
        end;
     end;
  end;
  {$endif}


  function Execute( psExeName:string):integer;
  begin
     {$ifdef windows} result := LocalExecute(psExeName, false , SW_SHOW);   {$endif}
     {$ifdef win32}   result := LocalExecute32(psExeName, false , SW_SHOW); {$endif}
  end;

Note: please try these out on your Delphi version and Operating system (I have developed them under Delphi 7 and used them under Windows XP).

If you want native printing (without Acrobat reader installed - but who hasn't installed Acrobat Reader these days?) you might consider the following component set: Pdft print components from WpCubed.

UPDATE

Upon request I added the Execute function from my library ...

Solution 3

There is a shareware-prog called 'AutoPrint' that sends all files in a folder to a printer, cost 35 dollar. (if u dont have many customers).

Otherwise it would be cool if someone could fix some code that does the same.

Solution 4

Printing a PDF to a printer without attempting to use Adobe Reader from Delphi can be done using Debenu Quick PDF Library, which supports all versions of Delphi from 4 to XE8. Sample code for printing a PDF programmatically without previewing it first:

procedure TForm6.PrintDocumentClick(Sender: TObject);
var
iPrintOptions: Integer;
begin
  DPL := TDebenuPDFLibrary1115.Create;
  try
    UnlockResult := DPL.UnlockKey('...'); // Add trial license key here
    if UnlockResult = 1 then
      begin
          // Load your file
          DPL.LoadFromFile('test.pdf', '');

          // Configure print options
          iPrintOptions := DPL.PrintOptions(0, 0, 'Printing Sample');

          // Print the current document to the default printing
          // using the options as configured above
          DPL.PrintDocument(DPL.GetDefaultPrinterName(), 1, 1, iPrintOptions);
      end;
    finally
    DPL.Free;
  end;
end;

More advanced printing options are also available using the customer printer functions. It's not a free SDK, but it will do exactly what you want.

Share:
37,509
Liezzzje
Author by

Liezzzje

Nothing interesting, really

Updated on August 15, 2020

Comments

  • Liezzzje
    Liezzzje over 3 years

    I have been looking online for some time now, but I still haven't figured out how to print a PDF file in Delphi without showing the document itself, or a print dialog. I just want to open a file without showing it, and print it to the default printer.

    I'm trying to print a batch of PDF documents, and there is no need for user interference.