Do you own a Debenu Quick PDF Library version 7, 8, 9, 10, 11, 12, 13 or iSEDQuickPDF license? Upgrade to Debenu Quick PDF Library 14 today!

Debenu Quick PDF Library - PDF SDK Community Forum Homepage
Forum Home Forum Home > For Users of the Library > Sample Code
  New Posts New Posts RSS Feed - Delphi DDE to Acrobat
  FAQ FAQ  Forum Search   Register Register  Login Login

Delphi DDE to Acrobat

 Post Reply Post Reply
Author
Message
hbarclay View Drop Down
Team Player
Team Player


Joined: 29 Oct 05
Location: United States
Status: Offline
Points: 39
Post Options Post Options   Thanks (0) Thanks(0)   Quote hbarclay Quote  Post ReplyReply Direct Link To This Post Topic: Delphi DDE to Acrobat
    Posted: 20 Dec 06 at 6:02PM
The Unit below is an attempt to convert the pdfp command line program for use in Delphi. It seems to work, but I am not real fluent in C so I'm sure there will be some issues to be found with it.

I would welcome any suggestions on improving it.

There is only one function to call, (Printpdf). Pass in the filename, printer name and the three other parameters as described in the pdfp program

    -o orientation : set orientation
        1=portrait, 2=landscape

    -d duplex : set duplex mode (if supported by printer)
        1=none, 2=long side, 3=short side

    -c copies : set number of copies to print
        copies=1 to 99

I put in the code to look for Adobe 8 so it should work with it, but I have not tested at all with version 8, nor did I put in the additional commands that are in pdfp8.


----------------------------------------------------------------------------------------

unit pdfdde;

// Delphi conversion of pdfp command line program from
// http://www.esnips.com/web/PDFTools

interface

// FileName must contain complete path
function PrintPdf(Filename,PrinterName : string;Orientation,duplex,copies : integer): boolean;

implementation
uses windows,ShellAPI,sysutils,messages,ddeman,winspool,printers;

var
  hWndAdobe : HWND;

function SetPrinterProperties(pPrinterName : pChar;pDevModeNew : PDEVMODE) : boolean;
var
    hPrinter : THandle;
    dwNeeded : DWORD;
    pi2 : PPrinterInfo2;
    pDevModeVar : PDEVMODE;
    pDevModeVar2 : PDEVMODE;
    pd : PRINTER_DEFAULTS;
    bFlag : boolean;
    lFlag : integer;
begin
    // Open printer handle
    ZeroMemory(@pd, sizeof(pd));
    pd.DesiredAccess := PRINTER_ACCESS_USE; //PRINTER_ALL_ACCESS;
    bFlag := OpenPrinter(pPrinterName, hPrinter, @pd);
    if (bFlag = false) or (hPrinter = 0) then
  begin
        result := FALSE;
    exit;
  end;

    // The first GetPrinter tells you how big the buffer should be in
    // order to hold all of PRINTER_INFO_2. Note that this should fail with
    // ERROR_INSUFFICIENT_BUFFER.  If GetPrinter fails for any other reason
    // or dwNeeded isn't set for some reason, then there is a problem...
    SetLastError(0);
    bFlag := GetPrinter(hPrinter, 2, nil, 0, @dwNeeded);
         if ((bFlag) or (GetLastError() <> ERROR_INSUFFICIENT_BUFFER) or (dwNeeded = 0)) then
         begin
           ClosePrinter(hPrinter);
           result := FALSE;
           exit;
         end;

    // Allocate enough space for PRINTER_INFO_2...
  GetMem(pi2, dwNeeded);
    if (pi2 = nil) then
    begin
        ClosePrinter(hPrinter);
        result := FALSE;
    exit;
  end;

    // The second GetPrinter fills in all the current settings, so all you
    // need to do is modify what you're interested in...
    bFlag := GetPrinter(hPrinter, 2, pi2, dwNeeded, @dwNeeded);
    if (bFlag = false) then
    begin
    freemem(pi2);
        ClosePrinter(hPrinter);
        result := FALSE;
    exit;
  end;


    // If GetPrinter didn't fill in the DEVMODE, try to get it by calling
    // DocumentProperties...
    if (pi2.pDevMode = nil) then
    begin
    dwNeeded := DocumentProperties(0,
       hPrinter,       //* Handle to our printer. */
       pPrinterName,        //* Name of the printer. */
       pDevModevar^,           //* Asking for size, so */
       pDevModeVar2^,           //* these are not used. */
       0);             //* Zero returns buffer size. */

        if (dwNeeded <= 0) then
        begin
            FreeMem(pi2);
            ClosePrinter(hPrinter);
            result := FALSE;
        end;

    GetMem(pDevModeVar,dwneeded);

        lFlag := DocumentProperties(0, hPrinter,
                        pPrinterName,
                        pDevModeVar^, pDevModeVar2^,
                        DM_OUT_BUFFER);

        if (lFlag <> IDOK) or (pDevModeVar = nil) then
        begin
            FreeMem(pDevModeVar);
            FreeMem(pi2);
            ClosePrinter(hPrinter);
            result := FALSE;
        end;

        pi2.pDevMode := pDevModeVar;
    end;

    if (pDevModeNew.dmFields and DM_COPIES) <> 0 then
        if(pi2.pDevMode.dmCopies <> pDevModeNew.dmCopies) then
    begin
            // Specify exactly what we are attempting to change...
            pi2.pDevMode.dmFields := pi2.pDevMode.dmFields or DM_COPIES;
            pi2.pDevMode.dmCopies := pDevModeNew.dmCopies;
    end;


    if (pDevModeNew.dmFields and DM_ORIENTATION <> 0) then
        if(pi2.pDevMode.dmOrientation <> pDevModeNew.dmOrientation) then
    begin
            // Specify exactly what we are attempting to change...
            pi2.pDevMode.dmFields := pi2.pDevMode.dmFields or DM_ORIENTATION;
            pi2.pDevMode.dmOrientation := pDevModeNew.dmOrientation;
    end;

    if (pDevModeNew.dmFields and DM_DUPLEX) <> 0 then
    if(pi2.pDevMode.dmDuplex <> pDevModeNew.dmDuplex) then
    begin
            // Specify exactly what we are attempting to change...
            pi2.pDevMode.dmFields := pi2.pDevMode.dmFields or DM_DUPLEX;
            pi2.pDevMode.dmDuplex := pDevModeNew.dmDuplex;
    end;

    if (pDevModeNew.dmFields and DM_SCALE) <> 0 then
        if(pi2.pDevMode.dmScale <> pDevModeNew.dmScale) then
    begin
            // Specify exactly what we are attempting to change...
            pi2.pDevMode.dmFields := pi2.pDevMode.dmFields or DM_SCALE;
            //pi2.pDevMode.dmNup = DMNUP_SYSTEM;
      pi2.pDevMode.dmDisplayFlags := 1;
            pi2.pDevMode.dmScale := pDevModeNew.dmScale;
    end;


    // Do not attempt to set security descriptor...
    pi2.pSecurityDescriptor := Nil;

    // Make sure the driver-dependent part of devmode is updated...
    lFlag := DocumentProperties(0, hPrinter,
          pPrinterName,
          pi2.pDevMode^, pi2.pDevMode^,
          DM_IN_BUFFER or DM_OUT_BUFFER);

    if (lFlag <> IDOK) then
    begin
        FreeMem(pi2);
        ClosePrinter(hPrinter);
        result := FALSE;
    exit;
  end;

    // Update printer information...
    bFlag := WinSpool.SetPrinter(hPrinter, 2, pi2, 0);

    // Note that this is triggered on network printers, although the values
    // get set, so we will ignore this for now
//*    if (!bFlag)
//    // The driver doesn't support, or it is unable to make the change...
//    {
//        GlobalFree(pi2);
//        ClosePrinter(hPrinter);
//        if (pDevMode)
//            GlobalFree(pDevMode);
//        return FALSE;
//    }
//*/
    // Tell other apps that there was a change...
    SendMessageTimeout(HWND_BROADCAST, WM_DEVMODECHANGE, 0,
              LPARAM(PChar(pPrinterName)),
              SMTO_NORMAL, 1000, PDWORD(nil)^);

    // Clean up...
    if (pi2 <> nil) then
        freemem(pi2);
    if (hPrinter <> 0) then
        ClosePrinter(hPrinter);

    result := TRUE;
end;

function GetPrinterDevMode(pDevice : PChar) :  PDEVMODE;

var
   hPrinter : THandle;
   pDevModeVar : PDEVMODE;
   pDevModeVar2 : PDEVMODE;
   dwNeeded : DWORD;
   dwRet : DWORD;
begin
   //* Start by opening the printer */
   if not OpenPrinter(pDevice, hPrinter, nil) then
   begin
       result := nil;
   end;

   // *
   // * Step 1:
   // * Allocate a buffer of the correct size.
   // *
   dwNeeded := DocumentProperties(0,
       hPrinter,       //* Handle to our printer. */
       pDevice,        //* Name of the printer. */
       pDevModevar^,           //* Asking for size, so */
       pDevModeVar^,           //* these are not used. */
       0);             //* Zero returns buffer size. */

   GetMem(pDevModeVar, dwNeeded);

   // *
   // * Step 2:
   // * Get the default DevMode for the printer
   // *
   dwRet := DocumentProperties(0,
       hPrinter,
       pDevice,
       pDevModeVar^,       //* The address of the buffer to fill. */
       pDevModeVar2^,           //* Not using the input buffer. */
       DM_OUT_BUFFER); //* Have the output buffer filled. */
   if (dwRet <> IDOK) then
   begin
       //* If failure, cleanup and return failure. */
       freemem(pDevModeVar);
       ClosePrinter(hPrinter);
       result := nil;
   end;

   //* Finished with the printer */
   ClosePrinter(hPrinter);

   //* Return the DevMode structure. */
   result := pDevModeVar;
end;

function GetExeName(FileName,FilePath : string; var PdfExeName,Msg : string; var RetCode : integer): Boolean;
var
  FileNameArray : array [0..MAX_PATH -1] of char;
  DefaultPathArray : array [0..MAX_PATH -1] of char;
  ResultArray : array [0..MAX_PATH -1] of char;

begin
  strpcopy(FileNameArray,FileName);
  strpcopy(DefaultPathArray,FilePath);
  RetCode := FindExecutable(FileNameArray,DefaultPathArray,ResultArray);
  PdfExeName := ResultArray;

Result := false;
  case RetCode of
      SE_ERR_NOASSOC : msg := 'File Association Not Found';
      SE_ERR_FNF : msg := 'File Not Found';
      SE_ERR_PNF : msg :=  'path not found ';
      SE_ERR_ACCESSDENIED : msg := 'access denied';
      SE_ERR_OOM : msg := 'out of memory ';
      SE_ERR_DLLNOTFOUND : msg := 'dll not found';
      SE_ERR_SHARE : msg := 'sharing error';
      SE_ERR_ASSOCINCOMPLETE : msg := 'association incomplete';
      SE_ERR_DDETIMEOUT : msg := 'DDE Timeout';
      SE_ERR_DDEFAIL : msg := 'DDE Failure';
      SE_ERR_DDEBUSY : msg := 'DDE Busy';
      else
        begin
         //I guess it worked
         Result := true;
         msg := 'Retcode ' + inttostr(RetCode);
        end;
  end;
end;

procedure HideAdobe;
begin
    ShowWindow (hWndAdobe, SW_RESTORE);
    MoveWindow (hWndAdobe, -100, -100, 0, 0, TRUE);
    ShowWindow (hWndAdobe, SW_RESTORE);
  ShowWindow (hWndAdobe, SW_HIDE);
end;

function IsAdobeRunning : boolean;
begin

  hWndAdobe := FindWindow('AdobeAcrobat', nil);

  if hWndAdobe > 0 then
    Result := true
     else
       begin
        hWndAdobe := FindWindow('AcrobatSDIWindow', nil);
        if hWndAdobe > 0 then
          Result := true
          else
            Result := false;
       end;
end;

function PrintPdf(Filename,PrinterName : string;Orientation,duplex,copies : integer): boolean;
var
  PrinterDevice : array[0..MAX_PATH -1] of char;
  PrinterDriver : array[0..MAX_PATH -1] of char;
  PrinterPort : array[0..MAX_PATH -1] of char;
  CommandBuff : array[0..2047] of char;
  FilePathName : array[0..MAX_PATH -1] of char;
  FileNameArray : array [0..MAX_PATH -1] of char;
  DefaultPathArray : array [0..MAX_PATH -1] of char;
  CommandStr : string;
  hPrinter: THandle;
  DeviceMode: THandle;
  dwNeeded : DWORD;
  ppi2 : PPrinterInfo2;
  Foundit : boolean;
  RetCode : integer;
  msg : string;
  FileNameStr : string;
  FilePathStr : string;
  DdeConv : TDdeClientConv;
  WasRunning : boolean;
  pDevMode1 : PDeviceMode;
  pDevMode2 : PDeviceMode;

begin

if (copies < 1) or (copies > 10) then copies := 1;

result := false;
FileNameStr := extractfilename(Filename);
FilePathStr := extractfilepath(Filename);
strpcopy(FileNameArray,FileNameStr);
strpcopy(DefaultPathArray,FilePathStr);
strpcopy(FilePathName,Filename);

Foundit := GetExeName(Filename,FilePathStr,FileNameStr,msg,RetCode);
if not Foundit then
begin
 //log errors here
 exit; //bail out - result = false
end;

                    // Make sure printer name is valid
          strPcopy(PrinterDevice,PrinterName);
                    if not OpenPrinter(PrinterDevice, hPrinter, nil) then
          begin
                        // If not valid, log the problem & get default printer
            printer.GetPrinter(PrinterDevice,PrinterDriver,PrinterPort,DeviceMode);
                      //log errors here
            if not OpenPrinter(PrinterDevice, hPrinter, nil) then
             begin
               //log errors here
               exit; //bail out - result = false
             end;
          end;
                    // Find out how much space is needed for printer info
                    GetPrinter(hPrinter, 2, nil, 0, @dwNeeded);
                    if (dwNeeded = 0) then
          begin
                        //log errors here
                        ClosePrinter(hPrinter);
            exit; //bail out - result = false
          end;

                    //// Allocate enough space for PRINTER_INFO_2...
           GetMem(ppi2, dwNeeded);
                      // The second GetPrinter() will fill in all the current information
          try
            if GetPrinter(hPrinter, 2, ppi2, dwNeeded, @dwNeeded)then
            begin
              strcopy(PrinterPort,ppi2.pPortName);
              strcopy(PrinterDriver,ppi2.pDriverName);
            end;
          finally
            freemem(ppi2);
                    ClosePrinter(hPrinter);
          end;

    // Get default printer settings
     pDevMode1 := GetPrinterDevMode(PrinterDevice);
  pDevMode2 := GetPrinterDevMode(PrinterDevice);

   pDevMode2.dmDuplex := duplex;
   pDevMode2.dmFields := pDevMode2.dmFields or DM_DUPLEX;
   pDevMode1.dmFields := pDevMode1.dmFields or DM_DUPLEX;

   if orientation = 2 then
        pDevMode2.dmOrientation := DMORIENT_LANDSCAPE
        else
          pDevMode2.dmOrientation := DMORIENT_PORTRAIT;
   pDevMode2.dmFields := pDevMode2.dmFields or DM_ORIENTATION;
   pDevMode1.dmFields := pDevMode1.dmFields or DM_ORIENTATION;

   pDevMode2.dmCopies := copies;
   pDevMode2.dmFields := pDevMode2.dmFields or DM_COPIES;
   pDevMode1.dmFields := pDevMode1.dmFields or DM_COPIES;

  SetPrinterProperties(PrinterDevice,pDevMode2);

WasRunning := true;

                if not IsAdobeRunning then
        begin
         WasRunning:=FALSE;

         ShellExecute(0,'open',FileNameArray,nil,nil,SW_HIDE);

                    Sleep(3000);

                    HideAdobe();

                    if not IsAdobeRunning then
                        Sleep(3000);

                    HideAdobe();

        end;

        DdeConv := TDdeClientConv.Create(nil);
        try

          DdeConv.SetLink('acroview','control');
          DdeConv.OpenLink;

          //CommandStr := '[FilePrintSilent("' + FilePathName + '")]';
            CommandStr := '[FilePrintTo("' + FilePathName +
            '","' +  PrinterDevice +
            '","' +  PrinterDriver +
            '","' +  PrinterPort +'")]';

          strpcopy(CommandBuff,CommandStr);

          DdeConv.ExecuteMacro(CommandBuff,false);
             //Log error here
          DdeConv.CloseLink;
          sleep(1000);
        finally
          DdeConv.Free;
          DdeConv := nil;
        end;

//TODO? make sure we are finished spooling first

    if not WasRunning then
  begin
          if IsAdobeRunning then
      begin
            Sleep(1000);
            // Ask Acrobat/Reader to close
            PostMessage (hWndAdobe, WM_CLOSE, 0, 0);
      end;
  end;

  SetPrinterProperties(PrinterDevice,pDevMode1);

result := true;
end;



end.

Back to Top
 Post Reply Post Reply
  Share Topic   

Forum Jump Forum Permissions View Drop Down

Forum Software by Web Wiz Forums® version 11.01
Copyright ©2001-2014 Web Wiz Ltd.

Copyright © 2017 Debenu. Debenu Quick PDF Library is a PDF SDK. All rights reserved. AboutContactBlogSupportOnline Store