BULLZIP PDF PRINTER as COM Object

Published on by Yousfi Benameur

         

Bullzip PDF Printer is one of the most complete and advanced tools to convert any printable document into PDF or into various image file formats. This tool is compatible with all Windows versions available, and you can use it for free for personal and non-commercial purposes.
Bullzip is  COM object( works with createObject or NewObject objects reside in registry and installed by bullzip application).
it works with a runOnce, an INI file configurating all parameters programmatly or manually by visual interface  (gui.exe shipped with).

Configuration files are basically text files similar to INI files in structure. They can be modified using the Options dialog or the Printer API. You can also open and edit the files using Notepad or any other suitable editor. The files can be saved using Unicode, UTF-8, or just plain ANSI encoding.

When a print job is sent to the program it will look for a runonce file. The runonce setting file is used to control the PDF creation from another program. A runonce settings file is only valid for one print job and will be removed automatically when it is read. All other settings files are ignored if a runonce file exists.

the free part of Bullzip is shipped under conditions (10 users max for personal use only).
for vfp files as prg,mpr,h,dbf must convert these files to a txt temp file accepted and convert to pdf.
see below how to find the locations of all configuration,status and log files set or retrieved by Bullzip app.

Bullzip supports as well unicode and ANSII.unicode can be (unicoe,UTF-8) 
must prefix the file content with a signature that identifies the encoding. Only ANSI files do not require any encoding. However, ANSI files cannot contain any international characters. When you use the printer API the encoding will be done by the API itself.

Unicode files are prefixed with two bytes 0xFF and 0xFE. This signature is for Little Endian Unicode. The other type of Unicode is named Big Endian Unicode and is prefixed with 0xFE followed by 0xFF. Little endian is preferred over big endian.
UTF-8 encoded files must be prefixed with the byte sequence 0xEF, 0xBB, 0xBF. 
the settings.ini must have this parameter if unicode.
-Bullzip accepts also command line (read the documentation for this purpose).



Click on code to select [then copy] -click outside to deselect


*1*
*download the free Bullzip PDF printer at :http://www.bullzip.com/products/pdf/info.php#download
*Install exe: Setup_BullzipPDFPrinter_10_24_0_2543_FREE (10.7Moctets).install only bulzip needed (there is also ghostScript shipped with installation) .
*warning: the print dialog fired is localized (french:"iprimer",english "print"..must set in code before run.
Clea All
Close Data All


Set Safe Off
Local m.yrep
m.yrep=Addbs(Justpath(Sys(16,1)))
Set Defa To (yrep)
Local lcPath,lcCurDir,lcDest,upr As String

Declare Integer SetDefaultPrinter In winspool.drv  String pszPrinter
Local m.upr
m.upr='Bullzip PDF Printer'
SetDefaultPrinter(m.upr)

Local m.cfilename,m.filter
m.filter="frx|prg|mpr|h|dbf|html|htm|jpg|bmp|png|gif|txt|pdf|doc|docx|rtf|xls|*"   &&...should be any printable file
m.cfilename = Getfile(m.filter)         && HOME(2)+'solution\reports\colors.frx' && Adding report &&try
If Empty(m.cfilename)
    Return .F.
Endi
If Inlist(Lower(Justext(m.cfilename)),"prg","mpr","h") &&files dont accepted--coberted to txt files
	Strtofile(Filetostr(m.cfilename),Addbs(Sys(2023))+"ytemp.txt")
	m.cfilename=Addbs(Sys(2023))+"temp.txt"
Endi

if Lower(Justext(m.cfilename))=="dbf"
local m.oo
m.oo=addbs(sys(2023))+"ytemp.txt"
sele * from (m.cfilename) into cursor ycurs
sele ycurs
copy to (m.oo) sdf
use in select("ycurs")
run/n notepad &oo
endi


Local m.xtype,m.xfilter
m.xfilter="PDF,EPS,PS,DOC,TXT,PCX,JPG,BMP,PNG,TIFF"
m.xtype=Inputbox("Output to "+m.xfilter,"","PDF")
If Empty(m.xtype) Or ! Inlist(Lower(m.xtype),"pdf","eps","ps","doc","docx","txt","pcx","jpg","bmp","png","tiff")
	m.xtype="PDF"
Endi


m.lcDest=m.yrep+Juststem(m.cfilename)+"."+m.xtype
Set Defa To (yrep)
m.lcPath=Putfile("File Name",m.lcDest,m.xtype)
m.lcDest=Addbs(Justpath(m.lcPath))+Justfname(lcPath)


Local m.oo
oo=.T.
Try
	lcObj = Createobject("BullZIP.PDFPrinterSettings")
	*should be also: CreateObject("bioPDF.PDFPrinterSettings")
Catch
	Messagebox("Bullzip printer not installed",16+4096,"Bullzip install Error")
	oo=.F.
Endtry
If m.oo=.F.
	Return .F.
Endi

Local m.multi
m.multi=.F.


If Lower(Justext(m.lcDest))=="tiff"
	m.multi=.T.  &&set one tiff multipage (otherwise separate pages)-can set this in settings dialog appearing
Endi

*this is exhaustive printer settings can config with COM automation
*see the ini file created automatically to get all object properties and what you have set.

With lcObj

	Do Case
		Case Inlist(Lower(Justext(m.lcDest)),"jpg","png","bmp","pcx","tiff")
			.SetValue("resx",150)
			.SetValue("resy",150)
			.SetValue("textalphabits",4)
			.SetValue("graphicsalphabits",4)
			.SetValue("ShowSettings" ,"YES")   &&"NEVER")   &&otherwise 1 page is pinted only.
			If m.multi=.F.
				.SetValue("output",Addbs(Justpath(m.lcDest))+Juststem(m.lcDest)+"<pageno>"+"."+m.xtype)
			Else
				.SetValue("output",m.lcDest)
			Endi

		Otherwise

			If Lower(Justext(m.lcDest))=="txt"
				.SetValue("ShowSettings" ,"YES")
				.SetValue("output",Addbs(Justpath(m.lcDest))+Juststem(m.lcDest)+"<pageno>"+"."+m.xtype)
			Else
				.SetValue("ShowSettings" ,"NEVER")
				.SetValue("output",m.lcDest)
			Endi
	Endcase


	.SetValue("WatermarkText" ,"Visual Foxpro Rock")
	.SetValue("WatermarkColor","")    &&"#FF8000")   &&"COCOCO")  or "#FF9900")  ...
	.SetValue("WatermarkTransparency",70)    &&0 to 100 (normal values:70-90)
	.SetValue("WatermarkRotation","c2c")   &&0-360 degrees
	.SetValue("WatermarkSize",6)    &&1-100  normal=6
	.SetValue("watermarkoutlinewidth",2)
    
    * Place a stamp in the lower right corner
    *    .SetValue( "WatermarkText", "Yousfi.over-blog.com")
    *    .SetValue( "WatermarkVerticalPosition", "bottom")
    *    .SetValue( "WatermarkHorizontalPosition", "right")
    *    .SetValue( "WatermarkVerticalAdjustment", "3")
    *    .SetValue( "WatermarkHorizontalAdjustment", "1")
    *    .SetValue( "WatermarkRotation", "90")
    *    .SetValue ("WatermarkColor", "#ff0000")
    *    .SetValue ("WatermarkOutlineWidth", "1")

    
	.SetValue("ShowPDF" ,"yes")
	.SetValue("AutoRotatePages" ,"none")
	.SetValue("Orientation", "portrait")  &&landscape
	.SetValue("ShowProgress", "yes")
	.SetValue("ShowProgressFinished", "yes")
	.SetValue("zoom","default")  &&"50%"  && "fitall"
	.SetValue ("ConfirmOverwrite", "no")
	.SetValue ("ShowSaveAS", "never" )
	.SetValue("StatusFileEncoding", "unicode")  &&ASCII
    .Setvalue("icc","yes")   && color print ?
	.SetValue ("RememberLastFileName", "no")
	.SetValue ("RememberLastFolderName", "no")
	.SetValue("usedefaultauthor","no")
	.SetValue("title","")    &&no title
	.SetValue("usedefaulttitle","yes")
    .SetValue("UseThumbs","yes")  &&"no"
	.WriteSettings(.T.)  &&Write the settings to the runonce.ini file
Endwith


If  Lower(Justext(m.cfilename))=="frx"
	Use (m.cfilename) Alias ycurs
	Sele ycurs
	Locate For objtype=1 And objcode=53
	If Found()
		Repl Expr With Strtran(Expr,"COLOR=1","")  &&to avoid black & white in some cases
		Repl Tag With "",tag2 With ""
		*brow
	Endi
	Use In Select("ycurs")
	*set reportbehavior 90
	Repo Form (m.cfilename)  Noconsole To Print
	Set Printer To

	lcObj=Null
	Release lcObj
	Clea Dlls
	Return
Endi


_Screen.WindowState=0

Local m.upr
m.upr="Bullzip PDF Printer"
Local m.myvar
TEXT to m.myvar textmerge noshow
rundll32.exe  PRINTUI.DLL,PrintUIEntry /y /n  "<<m.upr>>"
rundll32.exe %windir%\system32\mshtml.dll,PrintHTML "<<m.cfilename>>"
ENDTEXT
Strtofile(m.myvar,"ybat.bat")


Local oshell
oshell=Newobject("wscript.shell")
oshell.Run("ybat.bat",0,.F.)  &&dont wait and cmd.exe invisible
Inke(3)

*this function find the print wndow (localized) and send a return to it to pass.
=yhierarchy ( "imprimer")  &&localized in english:print

Dele File ybat.bat"

Try
	Erase Addbs(Sys(2023)+"ytemp.txt"  &&clean
Catch
Endtry

lcObj=Null
Release lcObj
Clear Dlls
********
Return

Function yhierarchy()
	Lparameters tcTitle
	* tcTitle="Imprimer"
	#Define WM_CLOSE 0x0010
	Do Decl

	Local hParent, hWindow, cTitle, cRect
	hParent = GetDesktopWindow()
	hWindow = 0

	Create Cursor cs (winhandle I,;
		x0 I, y0 I, x1 I, y1 I, wintitle C(200))

	Do While .T.
		Store Replicate(Chr(0),255) To cClass, cTitle
		hWindow = FindWindowEx(hParent, hWindow,;
			Null, Null)

		If hWindow = 0
			* 123=ERROR_INVALID_NAME
			* 127=ERROR_PROC_NOT_FOUND
			*? "Exit on error:", GetLastError()
			Exit
		Else
			cTitle = GetWinText(hWindow)
			cRect = GetWinRect(hWindow)

			Insert Into cs Values (hWindow,;
				buf2dword(Substr(cRect, 1,4)),;
				buf2dword(Substr(cRect, 5,4)),;
				buf2dword(Substr(cRect, 9,4)),;
				buf2dword(Substr(cRect, 13,4)),;
				cTitle)
		
		Endif
	Enddo

	Select cs
	Locate
	#Define WM_ACTIVATE 0x0006
	Scan
		If Lower(tcTitle) $ Lower(wintitle)
			SendMessage(winhandle,WM_ACTIVATE,0,0)

			Local xoshell
			xoshell=Newobject("wscript.shell")
			xoshell.sendkeys("{ENTER}")
			xoshell=Null
		Endi
	Endscan
	* end

Function GetWinText(hWindow)
	Local cBuffer
	cBuffer = Replicate(Chr(0), 255)
	= GetWindowText(hWindow, @cBuffer, Len(cBuffer))
	Return Strtran(cBuffer, Chr(0), "")

Function GetWinRect(hWindow)
	Local cBuffer
	cBuffer = Replicate(Chr(0), 16)
	= GetWindowRect(hWindow, @cBuffer)
	Return cBuffer

Procedure Decl
	Declare Integer GetLastError In kernel32
	Declare Integer GetDesktopWindow In user32

	Declare Integer FindWindowEx In user32;
		INTEGER hwndParent, Integer hwndChildAfter,;
		STRING @lpszClass, String @lpszWindow

	Declare Integer GetWindowText In user32;
		INTEGER HWnd, String @lpString, Integer nMaxCount

	Declare Integer GetWindowRect In user32;
		INTEGER HWnd, String lpRect
	Declare Integer SendMessage In Win32API;
		INTEGER HWnd,;
		INTEGER uMsg,;
		INTEGER wParam,;
		INTEGER Lparam

Function buf2dword(lcBuffer)
	Return Asc(Substr(lcBuffer, 1,1)) + ;
		BitLShift(Asc(Substr(lcBuffer, 2,1)),  8) +;
		BitLShift(Asc(Substr(lcBuffer, 3,1)), 16) +;
		BitLShift(Asc(Substr(lcBuffer, 4,1)), 24)

Endfunc



Click on code to select [then copy] -click outside to deselect


-bullzip generates an INI file (called runOnce) and its configuration is executed before printing.
of course there is default configuration lines but can make programmatly each parameter of the ini file.See the code above with [.setvalue(any parameter,valid value])...

when you set configuration programmatly( as the code above) you can see your seetings in this ini file:
C:\Users\yousfi\AppData\Roaming\PDF Writer\Bullzip PDF Printer\settings.ini  (in my windows 10)

when run Bullzip , it retrieves a status.ini and job.ini located in temp folder.

-for more knowledge, can read Bullzip documentation as follow:
PDF Printer - User Guide  : http://www.bullzip.com/products/pdf2/doc/info.php
configuration: http://wiki.bullzip.com/pdf-printer/documentation/reference/configuration-files
               http://www.biopdf.com/guide/configuration_files.php
Settings: http://www.biopdf.com/guide/settings.php
macro tags:http://www.biopdf.com/guide/macro_tags.php#docname



Note : all the ini file can be set manually with the GUI.exe shipped with the Bullzip download.
Run C:\Program Files\Bullzip\PDF Printer\gui.exe and you can set manually all settings.ini parameters.

from vfp type in command window+return:
run/n "C:\Program Files\Bullzip\PDF Printer\gui.exe"

to locate configurations files and result files returned run this in command window:
run/n "C:\Program Files\Bullzip\PDF Printer\gui.exe" info printer="Bullzip PDF Printer"
these files are simple txt ones (notepad).open ans see what it returns.

*notes

*http://www.biopdf.com/guide/settings.php
*<pageno> macro    Page number for use in image creation. When creating images there will typically be one
*output file for each page in the original document. By using additional information in the <pageno>
*macro, you can control the padding width and character. <pageno,3> will pad the page number to a
*width of 3 characters (001, 002, etc.). <pageno,3,-> will use a dash as padding character and
*produce a different result (--1, --2, etc.). more...
*note: can configure other macros


*Format
*version 6.0.0.865 	Use this setting to make the resulting PDF document PDF/A-1B compliant. The default
* value is blank. If you change the value to pdfa1b it will try to make the document PDF/A-1b compliant.


Click on code to select [then copy] -click outside to deselect


[ PDF Printer ]
  output=<desktop>\<smarttitle>.pdf
  confirmoverwrite=yes
  confirmnewfolder=yes
  appendifexists=no
  rememberlastfilename=no
  rememberlastfoldername=yes
  openfolder=no
  showpdf=ask
  showsaveas=nofile
  showsettings=never
  suppresserrors=yes
  device=pdfwrite
  resx=150
  resy=150
  textalphabits=4
  graphicsalphabits=4
  author=
  title=
  subject=
  keywords=
  usedefaultauthor=no
  usedefaulttitle=no
  target=default
  compatibilitylevel=1.5
  zoom=default
  format=
  imagecompression=yes
  linearize=no
  usethumbs=no
  watermarktext=
  watermarkfontsize=45
  watermarkrotation=c2c
  watermarkcolor=#D9D9D9
  watermarkfontname=arial.ttf
  watermarkoutlinewidth=2
  watermarklayer=top
  watermarkverticalposition=center
  watermarkhorizontalposition=center
  watermarkverticaladjustment=
  watermarkhorizontaladjustment=
  mergefile=
  mergeposition=bottom
  superimpose=
  superimposeresolution=
  superimposelayer=bottom
  ownerpassword=
  userpassword=
  keylength=128
  permissions=
  uploadprotocol1=
  uploadserveraddress1=
  uploadserverport1=
  uploadusername1=
  uploadpassword1=
  uploadremotefile1=
  uploadlservervalidationtype1=none
  uploadknownhosts1=
  uploadauthenticationtype1=password
  uploadprivatekeyfile1=
  uploadprivatekeypassword1=
  deleteoutput=no
  signstorelocation=none
  signcertificate=
  signthumbprint=
  signstorename=my
  signpassword=
  signreason=
  showsignature=no
  runonsuccess=
  runonsuccessdir=
  runonsuccessmode=normal
  runonerror=
  runonerrordir=
  runonerrormode=normal
  afterprintprogram=
  afterprintprogramdir=
  afterprintprogrammode=normal
  colormodel=
  embedallfonts=yes
  subsetfonts=yes
  autorotatepages=
  orientation=
  showprogress=yes
  showprogressfinished=yes



images are printed as one page by default.check for multi pages file conversion as images or set macro param <pageno>.
images are printed as one page by default.check for multi pages file conversion as images or set macro param <pageno>.
images are printed as one page by default.check for multi pages file conversion as images or set macro param <pageno>.
images are printed as one page by default.check for multi pages file conversion as images or set macro param <pageno>.
images are printed as one page by default.check for multi pages file conversion as images or set macro param <pageno>.
images are printed as one page by default.check for multi pages file conversion as images or set macro param <pageno>.
images are printed as one page by default.check for multi pages file conversion as images or set macro param <pageno>.

images are printed as one page by default.check for multi pages file conversion as images or set macro param <pageno>.

Click on code to select [then copy] -click outside to deselect


*2*
* Create the objects to control the printer settings.

*set default printer to Bullzip

 Local lcobj
lcobj = Createobject("BullZIP.PDFPrinterSettings")

with lcObj
text to m.myvar textmerge noshow
-printer name :<<.GetPrinterName()>>
-Filename: <<.GetsettingsFilename>>
-Version: <<.GetVersion()>>
endtext
endwith
messagebox(m.myvar)

lcObj=null


  * Get default printer name
   oPrinterSettings = CreateObject("bullzip.PdfSettings")
   oPrinterUtil = CreateObject("bullzip.PdfUtil")
   sPrinterName = oPrinterUtil.DefaultPrintername
   oPrinterSettings.Printername = sPrinterName


Declare Integer SetDefaultPrinter In winspool.drv  String pszPrinter
SetDefaultPrinter(m.sPrinterName )
oPrinterSettings=null
oPrinterUtil =null

messagebox("default printer set="+sprinterName)


Click on code to select [then copy] -click outside to deselect


*3*
*the Bullzip com object cannot be seen in vfp/options\controls as activex /com object.its interface are set on registry.
*that why cannot embed the com object on vfp object browser to see its PEM and interfaces (to confirm).
*can use the Amembers function to retrieve its PEM as follow:
*this object have not visible properties (all are set in settingd.INI file) but have some methods.

Local lcobj
lcobj = Createobject("BullZIP.PDFPrinterSettings")
N= Amembers(gaPropArray, lcobj,3 )
Create Cursor ycurs ( col1 c(50),col2 c(8),col3 c(80),col4 M)
For i=1 To N
    Insert Into ycurs Values (gaPropArray(i,1),gaPropArray(i,2),gaPropArray(i,3),gaPropArray(i,4))
Endfor
lcobj=Null
Browse  Name ybrow   Title Trans(Reccount())+" Bullzip )"  Nowait    &&window as oop object
With ybrow
	.DeleteMark=.F.
	.GridLines=0
	.FontBold=.T.
	.Themes=.F.
	.RecordMark=.F.
	.SetAll("forecolor",255,"header")
	.SetAll("backcolor",Rgb(0,255,0),"header")
	.Columns(4).Width=100
	.Columns(1).DynamicBackColor="RGB(128,128,128)"
	.Columns(2).DynamicBackColor="RGB(100,140,240)"
	.Columns(3).DynamicBackColor="RGB(201,239,180)"
	.Columns(4).DynamicBackColor="RGB(120,140,40)"
	.HeaderHeight=24
	For i=1 To .ColumnCount
		.Columns(i).header1.FontSize=14
	Endfor
Endwith
locate


BULLZIP PDF PRINTER as COM Object

Click on code to select [then copy] -click outside to deselect


if Bullzip seems to be a perfect com tool to generate PDFs and make some utility conversions there is some dark points not solved as:

1-the  settings  dialog must appear to render multi pages for conversion to images or even txt files.
  the format is not set on this dialog and must be clicked manually to access to the follow.
  i suppose if i am not wrong that its made for commercial purpose to limit the free version.
  if this dialog is avoided the image are not readable at all.

2-its  free tool with conditions (personal use)-must purchase commercial product for large use.

3-conversion from doc,docx ,xls to pdf fails with com object.Tiff (see the code) can be separate files (one image per page) or multi TIFF (1 navigable file,1 page).
4-time to time i encountered bullzip fails problems(blank pages).

-the code above is a first try and  yet to perform with some additive tests.

Note:
to correct some problems relative to runonce ini file, must reset in the gui.exe (shipped with bullzip installation) to the default(can be done programmatly also).
to make Bullzip print to pdf any printable file, open this file and issue print in file menu (or CTRL+P).the printer dialog appears with selected default printer (choose Bullzip if not selected) .
a new dialog appears for saving the destination pdf file to select and its all.the pdf is printed as well



Important:All Codes above are tested on VFP9SP2 & windows 10 pro and Bullzip PDF Printer 10.24.2543.

Please come back with any bug.correcting code is usefull to all readers.

To be informed of the latest articles, subscribe:
Comment on this post
M
We specialize in producing and fulfilling the printed manuals. You can placed an online order of wire-bound, ring-bound and also stapled documents.
Reply