Page 1 of 1

PrintingLibEx-an enhanced printing lib with preview option

Posted: Sat Mar 11, 2006 10:55 am
by Fraiser72
Hi,

for an application, that i developed at the moment, i need some
special printing functions, that was not included inPB at the moment.
So i make my own priting lib with some of the following function:
  • easy preview on an ListIconGadget()
  • printer setup and printing dialog
  • set the page orientation, size and color
  • all used koordinates in 1/10mm
  • frame, box, circle, ellipse and line function
  • formatted text output (multiline support)
  • image printing with keeping the pic aspect
  • an some other stuff
Download PrintingLibEx for PB 3.9x

Download PrintingLibEx for PB 4

Fraiser

Posted: Sat Mar 11, 2006 11:26 am
by Flype
Really good, i'm interested in using it.

Some questions :

1/
Any chance to implement anti-aliased drawing stuff, like in PurePDF ?

2/
And is it possible to save in a file the output ?

3/
What are the supported image formats (bmp,png,jpg,...) ?

4/
Do you planned to release the source code ?

5/
Is it possible to add the possibilty to manually set the printer device.
Something like PrintingExSetPrinterByName("Lexmark 730 series")

Thanks for sharing.

Posted: Sat Mar 11, 2006 1:12 pm
by Droopy
Nice and useful

Posted: Sat Mar 11, 2006 3:13 pm
by HAnil
for 3.94 examples not working.

PrintingLibInitEx()
and
ClosePrintingLibEx()

are unknown procedure.
When I remark this functions, program works.
do you control ?

Posted: Sat Mar 11, 2006 3:33 pm
by Fraiser72
Hi,

@HAnil
sorry, i removed this two functions because they are not needed
any more! The first call of any function will init the lib.

@Flype
1/
Any chance to implement anti-aliased drawing stuff, like in PurePDF ?
I will see.
2/
And is it possible to save in a file the output ?
Why would you save it to a file? For a printing lib, i think, it make no sense.
3/
What are the supported image formats (bmp,png,jpg,...) ?
At the moment bmp and jpeg are full supportet.
4/
Do you planned to release the source code ?
Yes.
5/
Is it possible to add the possibilty to manually set the printer device.
Something like PrintingExSetPrinterByName("Lexmark 730 series")
Yes, it is posible. I will try to include it in the next versions.

Fraiser

Posted: Sun Mar 12, 2006 3:17 am
by DoubleDutch
Nice Lib :)

If you use the "PrintingTextBoxEx" command and the text does not fit in the box (height-wise), is there any way to see how much of the text has printed?

It could return the number of characters into the string that were used?

This way the programmer could remove that amount from the front of the string and carry on from where he/she left off in another box?

Bookmarks are also a nice idea that I've seen in other print preview systems, could you add those?

Posted: Sun Mar 12, 2006 6:49 pm
by ABBKlaus
could it be possible to include the following routines :

Code: Select all

ProcedureDLL.l Printing_GetFontAscent(DC)
  GetTextMetrics_(DC,TM.TEXTMETRIC)
  ;Debug "tmHeight="+Str(TM\tmHeight)
  ;Debug "tmAscent="+Str(TM\tmAscent)
  ;Debug "tmDescent="+Str(TM\tmDescent)
  ProcedureReturn TM\tmAscent
EndProcedure

ProcedureDLL.l Printing_TextHeight(DC,Text$)
  GetTextExtentPoint32_(DC,Text$,Len(Text$),TextH.SIZE)
  Debug Text$+"="+Str(TextH\cy)
  ProcedureReturn TextH\cy
EndProcedure

ProcedureDLL.l Printing_TextWidth(DC,Text$)
  GetTextExtentPoint32_(DC,Text$,Len(Text$),TextL.SIZE)
  Debug Text$+"="+Str(TextL\cx)
  ProcedureReturn TextL\cx
EndProcedure

ProcedureDLL.s Printing_GetDefaultPrinter()
  PrinterName$=""
  If OSVersion()<#PB_OS_Windows_2000
    Len=260
    PrinterName$=Space(Len)
    GetPrivateProfileString_("WINDOWS","DEVICE","",@PrinterName$,Len,"Win.Ini")
    PrinterName$=StringField(PrinterName$,1,",")
  Else
    winspool=OpenLibrary(#PB_Any,"WINSPOOL.DRV")
    If winspool
      Len=260
      PrinterName$=Space(260)
      CallFunction(winspool,"GetDefaultPrinterA",@PrinterName$,@Len)
      If GetLastError_()=#ERROR_FILE_NOT_FOUND
        PrinterName$=""
      EndIf
    EndIf
    CloseLibrary(winspool)
  EndIf
  ProcedureReturn PrinterName$
EndProcedure
Please make your lib more API compatible :wink:

Posted: Tue Mar 14, 2006 8:27 pm
by ABBKlaus
no reply :?:
ok than i put down my trousers :oops:
i am currently workin on a barcode library (for the PurePDF - lib its almost done) but for printing directly to a printer i need some more commands :
GetFontSize()
GetStringWidth()
Klaus

Code: Select all

#PDF_BARCODE_FULL_CODE39      = $001 ; included
#PDF_BARCODE_REGULAR_CODE39   = $002 ; included
#PDF_BARCODE_CODE93           = $003 ; included
#PDF_BARCODE_CODE128          = $004 ; included
#PDF_BARCODE_CODABAR          = $005 ; included
#PDF_BARCODE_DATAMATRIX       = $006
#PDF_BARCODE_MAXICODE         = $007
#PDF_BARCODE_PDF417           = $008
#PDF_BARCODE_QRCODE           = $009
#PDF_BARCODE_INTERLEAVED2OF5  = $00A ; included
#PDF_BARCODE_MSIPLESSEY       = $00B
#PDF_BARCODE_UPC_A            = $00C ; included
#PDF_BARCODE_UPC_E            = $00D ; included
#PDF_BARCODE_EAN13            = $00E ; included
#PDF_BARCODE_EAN8             = $00F ; included
#PDF_BARCODE_2DIGIT_SUPP      = $010 ; included
#PDF_BARCODE_5DIGIT_SUPP      = $011 ; included
#PDF_BARCODE_USPOSTNET        = $012
#PDF_BARCODE_AUSTRALIAPOST    = $013
#PDF_BARCODE_KIX              = $014
#PDF_BARCODE_ROYAL_MAIL       = $015

#PDF_BARCODE_CODE128_CODEA    = $001
#PDF_BARCODE_CODE128_CODEB    = $002
#PDF_BARCODE_CODE128_CODEC    = $003
#PDF_BARCODE_CODE128_AUTO     = $004
#PDF_BARCODE_CODE128_AUTOA    = $005

#PDF_TEXT_NOTEXT              = $000
#PDF_TEXT_CENTER              = $001
#PDF_TEXT_RIGHT               = $002
#PDF_TEXT_TOP                 = $004
#PDF_TEXT_BOTTOM              = $008

Procedure ipf_Barcode_Text_EAN(x.f,y.f,h.f,w.f,offsety.f,barpos.l,align.b,text.s)
  fontsize.f
  textx.f
  texty.f
  
  ;fontsize=ipf_GetFontSize()*0.70
  ; GetFontSize() not available in PrintingLibEx !!
  fontsize=10*0.70
  
  If Align<>#PDF_TEXT_NOTEXT
    If Align&#PDF_TEXT_TOP
      texty=y-(offsety)
    Else
      texty=y+offsety+fontsize+h
    EndIf
    ;textx=x+(barpos+1)*w+(((barpos+7)*w-barpos*w)/2-pdf_GetStringWidth(text)/2)
    ; GetStringWidth() not available in PrintingLibEx !!
    textx=x+(barpos+1)*w+(((barpos+7)*w-barpos*w)/2)
    ;pdf_Text(textx,texty,text)
    PrintingTextEx(text,textx,texty,0)
  EndIf
EndProcedure

Procedure ipf_Barcode_Print_Bar(x.f,y.f,h.f,w.f,code$)
  first.l
  last.l
  
  For i=1 To Len(code$)
    a$=Mid(code$,i,1)
    If a$="1" And first=0
      first=i
    EndIf
    If (a$="0" Or i=Len(code$)) And first<>0
      last=i-first
      If i=Len(code$) And a$<>"0"
        last+1
      EndIf
      ;pdf_Rect(x+first*w,y,last*w,h, #PDF_STYLE_FILL)
      PrintingBoxEx((x+first*w),y,((x+first*w)+(last*w)),(y+h),0)
      first=0
    EndIf
  Next
EndProcedure

Procedure ipf_Barcode_DrawEdgebar(x.f,y.f,h.f,w.f,barpos.l,edgebar.f,align.b,code.s)
  If Align&#PDF_TEXT_TOP
    ipf_Barcode_Print_Bar(x+barpos*w,y-edgebar,h+edgebar,w,code.s)
  Else
    ipf_Barcode_Print_Bar(x+barpos*w,y,h+edgebar,w,code.s)
  EndIf
EndProcedure

Procedure.s ipf_Check_Number(String.s)
  temp$=""
  For i=1 To Len(String)
    char$=Mid(String,i,1)
    If char$>="0" And char$=<"9"
      temp$+char$
    EndIf
  Next
  ProcedureReturn String
EndProcedure

Procedure.b ipf_Barcode_GetCheckDigit_EAN(barcode.s)
  ;Compute the check digit
  wSum.w=0
  res.b = 0
  For i = 0 To Len(barcode)-1
    If (Len(barcode)%2<>1 And i&1) Or (Len(barcode)%2 And i&1<>1)
      wSum + 3 * Val(Mid(barcode,i+1,1))
    Else
      wSum + 1 * Val(Mid(barcode,i+1,1))
    EndIf
  Next
  
  res = wSum % 10
  If (res>0)
    res =10 - res
  EndIf
  ProcedureReturn res  
EndProcedure

Procedure.s ipf_Barcode_GetBarcode_EAN(Type,index.l,barcode.s)
  parity.b
  adr.l
  
  If Type=#PDF_BARCODE_EAN13 Or Type=#PDF_BARCODE_UPC_A
    If index<7
      adr=(index-1) + Val( Mid(barcode,1,1) ) * 6
      If adr>59
        Debug "Address out of range ("+Str(adr)+")"
        parity=0
      Else
        parity=PeekB(?pdf_barcode_parities + adr)
      EndIf
    Else
      parity=2
    EndIf
    adr=Val(Mid(barcode,index+1,1))*8
    If adr>72
      Debug "Address out of range ("+Str(adr)+")"
      adr=0
    EndIf
  ElseIf Type=#PDF_BARCODE_EAN8
    If index<5
      parity=0
    Else
      parity=2
    EndIf
    adr=Val(Mid(barcode,index,1))*8
    If adr>72
      Debug "Address out of range ("+Str(adr)+")"
      adr=0
    EndIf
  EndIf
  
  ProcedureReturn PeekS(?pdf_barcode_codes + parity*80 + adr, 7)
EndProcedure

Procedure ipf_Barcode_EAN8(x.f,y.f,barcode.s,h.f,w.f,Align.b,offsety.f,edgebar.f,checkdigit.b)
; http://www.barcodeisland.com/ean8.phtml
  
  barcode=ipf_Check_Number(barcode)
  If Len(barcode)<7
    barcode=RSet(barcode,7,"0") ; Padding
  EndIf
  If Len(barcode)=7
    barcode+Str(ipf_Barcode_GetCheckDigit_EAN(barcode))
  EndIf
  ;If ipf_Barcode_TestCheckDigit_EAN(barcode)=#False
  ;  Debug "Incorrect check digit"
  ;EndIf
  ;Debug "EAN8:"+barcode
  
  ;Draw Bars
  
  barpos=1
  
  ;Left-hand guard bars
  ipf_Barcode_DrawEdgebar(x,y,h,w,barpos,edgebar,align,"101")
  barpos+3
  
  For i = 1 To Len(barcode)
    ; Center guard bars
    If i=5
      ipf_Barcode_DrawEdgebar(x,y,h,w,barpos,edgebar,align,"01010")
      barpos+5
    EndIf
    
    ;Convert digits To bars
    a$=ipf_Barcode_GetBarcode_EAN(#PDF_BARCODE_EAN8,i,barcode)
    ;print barcode
    ipf_Barcode_Print_Bar(x+barpos*w,y,h,w,a$)
    If i<8 Or (i=8 And checkdigit=#True)
      ipf_Barcode_Text_EAN(x,y,h,w,offsety,barpos,align,Mid(barcode,i,1))
    EndIf
    barpos+7
  Next
  
  ;Right-hand guard bars
  ipf_Barcode_DrawEdgebar(x,y,h,w,barpos,edgebar,align,"101")
  barpos+3
EndProcedure

DataSection
  pdf_barcode_parities:
  Data.b 0,0,0,0,0,0 ; 0
  Data.b 0,0,1,0,1,1 ; 1
  Data.b 0,0,1,1,0,1 ; 2
  Data.b 0,0,1,1,1,0 ; 3
  Data.b 0,1,0,0,1,1 ; 4
  Data.b 0,1,1,0,0,1 ; 5
  Data.b 0,1,1,1,0,0 ; 6
  Data.b 0,1,0,1,0,1 ; 7
  Data.b 0,1,0,1,1,0 ; 8
  Data.b 0,1,1,0,1,0 ; 9
  pdf_barcode_codes:
  Data.s "0001101" ; 0,0 left hand odd parity
  Data.s "0011001" ; 0,1
  Data.s "0010011" ; 0,2
  Data.s "0111101" ; 0,3
  Data.s "0100011" ; 0,4
  Data.s "0110001" ; 0,5
  Data.s "0101111" ; 0,6
  Data.s "0111011" ; 0,7
  Data.s "0110111" ; 0,8
  Data.s "0001011" ; 0,9
  Data.s "0100111" ; 1,0 left hand even parity
  Data.s "0110011" ; 1,1
  Data.s "0011011" ; 1,2
  Data.s "0100001" ; 1,3
  Data.s "0011101" ; 1,4
  Data.s "0111001" ; 1,5
  Data.s "0000101" ; 1,6
  Data.s "0010001" ; 1,7
  Data.s "0001001" ; 1,8
  Data.s "0010111" ; 1,9
  Data.s "1110010" ; 2,0 
  Data.s "1100110" ; 2,1
  Data.s "1101100" ; 2,2
  Data.s "1000010" ; 2,3
  Data.s "1011100" ; 2,4
  Data.s "1001110" ; 2,5
  Data.s "1010000" ; 2,6
  Data.s "1000100" ; 2,7
  Data.s "1001000" ; 2,8
  Data.s "1110100" ; 2,9
EndDataSection

ProcedureDLL print_Barcode_EAN8(x.f, y.f, barcode.s, h.f, w.f,Align.b,offsety.f, edgebar.f, checkdigit.b)
  ipf_Barcode_EAN8(x,y,barcode,h,w,Align,offsety,edgebar,checkdigit)
EndProcedure

;
;**** Demo App for the PrintingLibEx 
;**** (c) 2006 bei Fraiser (Gunnar Lühr)
;

Enumeration
  #MainWindow
  #BtnPrintDlg
  #BtnSetupDlg
  #BtnPrint
  #BtnPreview
  #BtnInfo
  #EditorInfo
  #CkdWidth
  #ListPreview
EndEnumeration

;*** Infos about printer an page
Procedure PrinterInfo()
    ClearGadgetItemList(#EditorInfo)
    AddGadgetItem(#EditorInfo, -1, "Width:   "+Str(GetPrintingCapsEx(#PL_PageSize_X))+"mm")
    AddGadgetItem(#EditorInfo, -1, "Height:  "+Str(GetPrintingCapsEx(#PL_PageSize_Y))+"mm")
    AddGadgetItem(#EditorInfo, -1, "Pixel X: "+Str(GetPrintingCapsEx(#PL_PhysicalSize_X)))
    AddGadgetItem(#EditorInfo, -1, "Pixel Y: "+Str(GetPrintingCapsEx(#PL_PhysicalSize_Y)))
    AddGadgetItem(#EditorInfo, -1, "DPI X:   "+Str(GetPrintingCapsEx(#PL_DPI_X)))
    AddGadgetItem(#EditorInfo, -1, "DPI Y:   "+Str(GetPrintingCapsEx(#PL_DPI_Y)))
    AddGadgetItem(#EditorInfo, -1, "Offset X:"+Str(GetPrintingCapsEx(#PL_Offset_X)))
    AddGadgetItem(#EditorInfo, -1, "Offset Y:"+Str(GetPrintingCapsEx(#PL_Offset_Y)))
    AddGadgetItem(#EditorInfo, -1, "Copies  :"+Str(GetPrintingCapsEx(#PL_PrintingCopies)))
    AddGadgetItem(#EditorInfo, -1, "Pages   :"+Str(GetPrintingCapsEx(#PL_PrintingPages)))
    AddGadgetItem(#EditorInfo, -1, "From    :"+Str(GetPrintingCapsEx(#PL_StartPage)))
    AddGadgetItem(#EditorInfo, -1, "To      :"+Str(GetPrintingCapsEx(#PL_EndPage)))
EndProcedure


;*** print loop with or without preview
Procedure PrintPreview(Preview)
  
  If Preview 
    ;*** start preview
    If GetGadgetState(#CkdWidth)
      ;*** set optional preview width
      RetStart.l = StartPrintingPreviewEx(#ListPreview, #True, 450)
    Else
      ;*** normal preview width with 72dpi
      RetStart.l = StartPrintingPreviewEx(#ListPreview, #True, 0)
    EndIf
  Else
    ;*** start printing
    RetStart.l = StartPrintingEx("Test Printing")
  EndIf
 
height.f=140
width.f=4.445
edgebar.f=15
xoffset.f=0
yoffset.f=0

  If RetStart.l
    PrintingFontEx("Arial", 60, #True)
    
    print_Barcode_EAN8(50,20,"5512345",height,width,#PDF_TEXT_BOTTOM,yoffset,edgebar,#True)
    ;print_Barcode_Code128(50,220,"12345678",height,width,#PDF_TEXT_BOTTOM,xoffset,yoffset,#PDF_BARCODE_CODE128_AUTO)
    
    If Preview
      ;*** end preview
      StopPrintingPreviewEx()
    Else
      ;*** end printing
      StopPrintingEx()
    EndIf
  Else
    MessageRequester("FEHLER", "Init Start Printing")
  EndIf
EndProcedure


;*** page setting
;If InitPrintingPageEx(#DMPAPER_A4, #DMORIENT_LANDSCAPE, #DMCOLOR_COLOR) = 0
If InitPrintingPageEx(#DMPAPER_A4, #DMORIENT_PORTRAIT, #DMCOLOR_COLOR) = 0
  MessageRequester("FEHLER", "Init PrintingPagebEx")
  End
EndIf

;** create window
If OpenWindow(#MainWindow, 50,50, 800, 800, #PB_Window_SystemMenu|#PB_Window_MaximizeGadget, "PrintingLibEx Test Application")
  If CreateGadgetList(WindowID(#MainWindow))
    ButtonGadget(#BtnPrintDlg, 20,20, 200, 24, "Open Print Dialog")
    ButtonGadget(#BtnSetupDlg, 20,60, 200, 24, "Open Print Setup")
    ButtonGadget(#BtnPrint, 20,100, 200, 24, "Print")
    ButtonGadget(#BtnPreview, 20,140, 200, 24, "Preview")    
    ButtonGadget(#BtnInfo, 20,420, 200, 24, "Info")
    EditorGadget(#EditorInfo, 20, 190, 200, 200)
    CheckBoxGadget(#CkdWidth, 20, 450, 200, 24, " - Preview breite begrenzen")
    
    ;*** IMPORTANT!! this gadget is used for the preview output
    ListIconGadget(#ListPreview, 240, 20, 540, 760, "", 0)
    ChangeListIconGadgetDisplay(#ListPreview, 0)  

    ;*** show info
    PrinterInfo()
         
    ;*** Main Loop
    Repeat
      Event.l = WaitWindowEvent()
  
      If Event.l = #PB_Event_Gadget
        Gadget.l = EventGadgetID()
      
        ;*** Print Dialog
        If Gadget.l = #BtnPrintDlg
          If PrintingDlgEx(WindowID(#MainWindow))
            PrintPreview(#False)
            PrinterInfo()   
          EndIf
       
        ;*** Printer Setup Dialog
        ElseIf Gadget.l = #BtnSetupDlg
          If PrinterSetupEx(WindowID(#MainWindow))
            PrinterInfo()
          EndIf
          
        ;*** print
        ElseIf Gadget.l = #BtnPrint
          PrinterInfo()
          PrintPreview(#False)
        
        ;*** preview
        ElseIf Gadget.l = #btnPreview
          PrintPreview(#True)
          
        ;*** show info
        ElseIf Gadget.l = #BtnInfo
          PrinterInfo()
          
        EndIf
      EndIf
    Until Event.l = #PB_Event_CloseWindow

  EndIf
  
EndIf

Posted: Tue Mar 14, 2006 9:37 pm
by Droopy
Very nice

Posted: Wed Mar 15, 2006 5:47 pm
by Fraiser72
Hi,

@ABBKlaus
Sorry, but at the moment i have much to do at the job so that i havent
so much time to work at the PrintingLibEx. What do you mean with
'Please make your lib more API compatible' ?
I didn't know if you see it, but a german version is also available
(http://www.purebasic.fr/german/viewtopi ... sc&start=0

Here is a little update with three new functions.

-GetPrintingFontMetricEx(Type) to get ascent,desent and height of the actual font
-GetPrintingTextHeightEx(Text$) to get the height of the given TEXT$
-GetPrintingTextWidthEx(Text$) to get the width of the given TEXT$

I hope this will help you a little bit. The function for the default printer name
is still in work.

Download PrintingLibEx for PB 3.9x

Download PrintingLibEx for PB 4

Fraiser

Posted: Wed Mar 15, 2006 6:18 pm
by ABBKlaus
Thanks that was fast :D
API compatible means :
when opening a printer return a 'PrinterHandle'
when opening a DC return a 'DCHandle'

Klaus

Posted: Fri Jan 26, 2007 7:07 pm
by QuimV
Hi,

I'm using this library and I need to know the units to use in the different types of GetPrintingCapsEx(Type) function.

Types are:

#PL_PageSize_X - Pagewidth in mm -> OK, clear!

#PL_PageSize_Y - Pageheight in mm -> OK, clear!

#PL_PhysicalSize_X - Physical pagewidth in dots (depends on the DPI resolution of the printer) -> Is the same dots and pixels?

#PL_PhysicalSize_Y - Physical pageheight in dots (depends on the DPI resolution of the printer) -> Is the same dots and pixels?

#PL_DPI_X - DPI resolution of the printer (horizontal) -> dots, OK!
#PL_DPI_Y - DPI resolution of the printer (vertikal) -> dots, OK!


#PL_Offset_X - non printable area ( left & right ) -> Units???

#PL_Offset_Y - non printable area ( top & bottom ) -> Units??


#PL_PrintingCopies - copies the user selected -> Number of copies, OK!

#PL_StartPage - start page -> Number of page to start printing, OK!

#PL_EndPage - end page -> Number of page to end printing, OK!

#PL_PrintingPages - amount of total pages ( available after preview) -> Number of total pages to print, OK!


I need to know the relation between dots and pixels?

Could anybody help me?

Thanks in advanced ...