zoukankan      html  css  js  c++  java
  • PDF Writer >an article on using virtual priter method to create pdf files

    the article come from codeproject http://www.codeproject.com/useritems/PDFWriter.asp

    Download PDFWriter demo project - 93 Kb

    introduction

    the main purpose of this paper is to demonstrate how to create a pdf writer by using virtual printer method, which gives you applications an ability to generate pdf file through simply "printing". i am pretty sure there are many pdf writer using the same technique, saying primoPdf. however you probably wish to create you own PDF writer in some day. i here give an example to  uncover the whole process of creating such kind of writer.

    background

    Ghostscript is an interpreter for pdf files, which also has an ability to convert PostScript language files to PDF.

    RedMon(http://www.cs.wisc.edu/~ghost/redmon/index.htm ) is a port monitor, which redirects a special printer port to Ghostscript.

    the main idea is actually simple. what you need to do is install a PostScript printer and let RedMon work as a bridge between the printer and the Ghostscript.

    using the code

    before jumping to the demo project

    You have to download Ghostscript. My demo requires AFPL Ghostscript 8.53 ( ftp://mirror.cs.wisc.edu/pub/mirrors/ghost/AFPL/gs853/gs853w32.exe ). Don’t install it at this time. You are encouraged to use WinRAR or WinZip (I didn’t try WinZip) to unzip it to “C:\\UTReportPrerequisite\\gs\\”.  You also need to copy pdfwrite.rsp( a text file, which can be found at demo project) to the folder as well.

    You may download RedMon from its website, but I suggest you use a replacement that packed in our demo project. There is a folder “redmon17” in demo project, please copy this folder to “C:\\UTReportPrerequisite\\”.

    The last thing you need is a printer driver. By chance, I chose HP color LaserJet 8550 PostScript driver (ftp://ftp.hp.com/pub/softlib/software3/lj1141/lj-5442-4/clj8550pswin2kxp2003-en.exe ). Also don’t install it at this time. Instead, use WinRAR to unzip all files to “c:\\UTReportPrerequisite\\Driver”.

    The final folder structure should be like below.

     
    Running the demo project

    Demo project is very straightforward. Clicking buttons from "Setp1", "Step2", "Step3" to "Setp4" sequentially, you may have a printer named "UTReport PDF Writer " installed if each step has been done successfully, as shown in figure below . I may point out that "Step3" and "Step4" are a little bit time consuming so that more patience should be paid.  

     

    Now it is the right time to test our PDF writer. Open WordPad.exe, type in whatever you want then print it using "UTReport PDF Writer". Check C:\SampleOut.PDF that is your output PDF file.

    "Step5" to "Setp8" let you have a chance to uninstall the printer you installed just now.

     

    Points of Interest

    1. AddPrinterDriver

          Based on MSDN: Before an application calls the AddPrinterDriver function, all files required by the driver must be copied to the system's printer-driver directory. An application can retrieve the name of this directory by calling the GetPrinterDriverDirectory function.  Therefore in our demo, we have to copy all printer driver files from c:\\UTReportPrerequisite\\Driver to the folder returned by GetPrinterDriverDirectory.  

    1. //Install Driver
      void CInstallPrinterDlg::OnBnClickedButtonStep3()
      {
          CString msg="Failed";
          if (CopyPrintDriverFiles2System() && AddPrinterDriver())
              msg = "Add Printer Driver Successfully";
         
          AfxMessageBox(msg);

          return ;
      }
    2. The other tricky thing is the pDependentFiles field of DRIVER_INFO_3. From MSDN: pDependentFiles is a pointer to a null-terminated string that specifies the files the driver is dependent on. Each file name in the string is also terminated with a null (for example, "Pscript.dll\0Qms810.PPD\0Pscrptui.dll\0Pspcriptui.hlp\0Pstest.txt\0\0"). How to assign a value to this field? My answer is
    3. DRIVER_INFO_3 di3;
      ...
      di3.pDependentFiles = TEXT("hpbafd32.dll\0hpbftm32.dll\0HPLJ8550.cfg\0hpcdmc32.dll\0hpbcfgre.dll\0hpdcmon.dll\0\0");

    4. Updating Registry

      In order to let our PDF Writer work like a charm, we have to update registry info for both Ghostscript and RedMon. For RedMon,

      Collapse
               //#define PORT_KEY TEXT("SYSTEM\\ControlSet001\\Control\\Print\\Monitors\\Redirected Port\\Ports\\UTReportPDFPort:")
          if ((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, PORT_KEY, 0, KEY_ALL_ACCESS, &hkey)) != ERROR_SUCCESS)
          {
          /* failed to open key, so try to create it */
          rc = RegCreateKey(HKEY_LOCAL_MACHINE, PORT_KEY, &hkey);
          }
          if (rc == ERROR_SUCCESS)
          {
          lstrcpy(buffer, "@c:\\UTReportPrerequisite\\gs\\pdfwrite.rsp -");
          RegSetValueEx(hkey, TEXT("Arguments"), 0, REG_SZ, (CONST BYTE *)buffer, lstrlen(buffer)+1);
          lstrcpy(buffer, "C:\\UTReportPrerequisite\\gs\\gs8.53\\bin\\gswin32c.exe");
          RegSetValueEx(hkey, TEXT("Command"), 0, REG_SZ,(CONST BYTE *)buffer, lstrlen(buffer)+1);
          dwValue =2;
          RegSetValueEx(hkey, TEXT("ShowWindow"), 0, REG_DWORD,(CONST BYTE *)&dwValue, 4);
          dwValue =0;
          RegSetValueEx(hkey, TEXT("RunUser"), 0, REG_DWORD,(CONST BYTE *)&dwValue, 4);
          dwValue =300;
          RegSetValueEx(hkey, TEXT("Delay"), 0, REG_DWORD,(CONST BYTE *)&dwValue, 4);
          RegCloseKey(hkey);
          }
          

      For Ghostscript ,

      Collapse
               //#define GHOSTSCRIPT_KEY2 TEXT("SOFTWARE\\AFPL Ghostscript\\8.53")
          if ((rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE, GHOSTSCRIPT_KEY2, 0, KEY_ALL_ACCESS, &hkey)) != ERROR_SUCCESS)
          {
          /* failed to open key, so try to create it */
          rc = RegCreateKey(HKEY_LOCAL_MACHINE, GHOSTSCRIPT_KEY2, &hkey);
          }
          if (rc == ERROR_SUCCESS)
          {
          lstrcpy(buffer, TEXT("C:\\UTReportPrerequisite\\gs\\gs8.53\\bin\\gsdll32.dll"));
          RegSetValueEx(hkey, TEXT("GS_DLL"), 0, REG_SZ, (CONST BYTE *)buffer, lstrlen(buffer)+1);
          lstrcpy(buffer, TEXT("C:\\UTReportPrerequisite\\gs\\gs8.53\\lib;C:\\UTReportPrerequisite\\gs\\fonts;C:\\UTReportPrerequisite\\gs\\gs8.53\\Resource"));
          RegSetValueEx(hkey, TEXT("GS_LIB"), 0, REG_SZ,(CONST BYTE *)buffer, lstrlen(buffer)+1);
          RegCloseKey(hkey);
          }
          
    5. About pdfwrite.rsp

      pdfwrite.rsp is actually a paramter file used to control PDF generation, i.e. page size, resolution etc. -sOutputFile is used to control where the produced PDF file should go. For more details, please read Ghostscrip online help.

      -Ic:\UTReportPrerequisite\gs\gs8.53\lib;c:\UTReportPrerequisite\gs\fonts
          -sDEVICE=pdfwrite
          -r600
          -dNOPAUSE
          -dSAFER
          -sPAPERSIZE=letter
          -sOutputFile="c:\SampleOut.PDF"
          

    Acknowledgement

    First of all, thanks all open source projects. Special thanks should be extended to Ghostscript and RedMon.

    History

    2006/03/16, First release.

    About Lu

    10 years more programming experience, strong at C++, Delphi, Database applications and C#. I am now working as a programmer in UTTechnology Inc., Edmonton, Alberta, Canada. 

    ben688


    Click here to view ben688's online profile.

  • 相关阅读:
    spring事务管理器设计思想(一)
    ThreaLocal内存泄露的问题
    denyhost防止SSH暴力破解
    qt下调用win32api 修改分辨率
    Windows下pip安装包报错:Microsoft Visual C++ 9.0 is required Unable to find vcvarsall.bat
    Centos 6.5 下安装socket5代理
    Mac 下安装mitmproxy
    Mac OS 下安装wget
    判断客户端是否使用代理服务器及其匿名级别
    Mac OS 下安装rar unrar命令
  • 原文地址:https://www.cnblogs.com/umlchina/p/createvirtualprintertoconvert.html
Copyright © 2011-2022 走看看