Printing using Win32lib.ew Functions

Since I haven't yet gotten around to changing the addressbook example to use the printing functions which are now a part of Win32lib, here's a little example that prints using these.

If you study the text and code in Extra02, you'll notice there aren't really that many differences.

Although the function names have changed slightly,
... you use:

getPrinter(), and
startDoc(), ... to get your ( printer ) document file started, then carry on ...

... with groups of:
startPage(),
endPage(), ... for each page, and then, finally:

endDoc(), and
releasePrinter(), ... to print a document.

A major difference is that getPrinter() calls a printer dialog box from which you can select a printer, and some of it's settings. Very nice !
My old version only used the Windows 'default' printer.

Instead of using 'my' pTextOut(), Win32lib uses setPenPos(), and wPuts(), to send text out to a printer page.

This example is a variation of pr123.exw, which shows how to 'wrap' a long text line to keep it on a page, and prints some simple graphics as well.

(... remember, that a printer page is basically a bitmap. If you send a long line to it, the excess will simply 'disappear' off the page's right margin unless you break up the line into smaller chunks first ! )

-- pr234.exw

include win32lib.ew

  integer junk, linecount, charsPerLine, linesPerPage,
  halfx, halfy
  sequence  fontSize, printerSize, text, lineOfText

constant
PrWin = create(Window,"Another Win32lib 'print'",0,10,10,300,210,0),
MenuP = create(Menu,"&Print",PrWin,0,0,0,0,0),
PNow  = create(MenuItem,"&A demo page !",MenuP,0,0,0,0,0)

-- a long text line
text = "I have been working on this tutorial since October of 1998, " &
 "starting with Win32lib version 0.15c, " &
 "and even though David added some 'wrappers' to Win32lib.ew for " &
 "printing " &
 "quite some time ago, " &
 "( in version 0.43e, Oct./99 ), it has taken me this long to finally " &
 "get around to using *his* functions " &
 "in a tutorial example !"

procedure get_info()
-- open the printer dialog
-- then, IF the user has selected a printer...
if length(getPrinter()) > 0 then
  -- pick a big fixed width font
  setFont( Printer, "Courier New", 24, Normal )
  -- get the font metrics
  fontSize = getFontSize( Printer )
  -- get the size of a printer page
  printerSize = getCtlSize( Printer )
  -- how many characters can fit on a line?
  charsPerLine = floor(printerSize[1]/fontSize[1])
  -- how many lines can fit on a page?
  linesPerPage = floor(printerSize[2]/fontSize[2])

-- report all the printer's 'metrics'
setPenPos(PrWin,10,10)
wPuts(PrWin,"...using the \"Courier New\", size 24 font.")
setPenPos(PrWin,10,30)
wPuts(PrWin,"character width = " & sprintf("%d",fontSize[1]))
setPenPos(PrWin,10,50)
wPuts(PrWin,"character height = " & sprintf("%d",fontSize[2]))
setPenPos(PrWin,10,70)
wPuts(PrWin,"characters per line = " & sprintf("%d",charsPerLine))
setPenPos(PrWin,10,90)
wPuts(PrWin,"lines per page = " & sprintf("%d",linesPerPage))
setPenPos(PrWin,10,120)
wPuts(PrWin,"page 'pixel' width = " & sprintf("%d",printerSize[1]))
setPenPos(PrWin,10,140)
wPuts(PrWin,"page 'pixel' height = " & sprintf("%d",printerSize[2]))

end if

end procedure


procedure print_now()
get_info()
-- start up the document
if startDoc( "My Print Job" ) then
  junk = startPage()
  -- set to top of page
  linecount = 0
  -- print until long text line is empty
  while length( text ) do
  -- get a line of text
    if length( text ) < charsPerLine then
        -- get remaining text
        lineOfText = text
        text = ""
    else
        -- get one 'printer line' of text
        lineOfText = text[1..charsPerLine]
        -- remove from remaining text
        text = text[charsPerLine+1..length(text)]

        -- is first character of line a space ?
        if equal(lineOfText[1], ' ') then
          lineOfText = lineOfText[2..length(lineOfText)]
          if length(text) > 0 then
            lineOfText = lineOfText & text[1]
          end if
          if length(text) > 1 then
            text = text[2..length(text)]
          end if
        end if

    end if
    -- position text on page
    setPenPos( Printer, 0, linecount*fontSize[2] )
    -- write the text
    wPuts( Printer,lineOfText )
    -- move down one line
    linecount += 1
    -- at bottom of page?
    if linecount > linesPerPage then
      -- print page
      if not endPage() then
        exit
      end if
      -- start a new page
      if not startPage() then
        exit
      end if
     -- reset counter
      linecount = 0
    end if
  end while

-- shucks, we know we haven't printed a full page yet...
-- so let's throw in some graphics, OK ?

-- draw a fat line half-way down the page.
halfy = floor(printerSize[2] / 2)
setPenWidth(Printer,5)
drawLine(Printer,0,halfy,printerSize[1],halfy)

-- draw a fat line at the bottom of the page.
setPenWidth(Printer,5)
drawLine(Printer,0,printerSize[2]-5,printerSize[1],printerSize[2]-10)

-- then draw a circle of size 50, at 20 by 20 below the top line.
setPenWidth( Printer,1 )
drawEllipse( Printer, True,  -- fill the circle
             20, halfy + 25,  -- start x,y
             20 + 50, halfy + 25 + 50 )  -- end x,y

-- then add a line of smaller text after the circle.
setFont( Printer, "Courier New", 16, Bold )
setPenPos( Printer, 100, halfy + 25 ) 
wPuts( Printer, "This makes a BIG point !" )

-- then add a big empty circle with a '400' diameter.
halfx = floor(printerSize[1] / 2)
setPenWidth( Printer, 4 )
drawEllipse( Printer, False,  -- don't fill the circle.
             halfx - 200, halfy + 100,  -- start x,y
             halfx + 200, halfy + 100 + 400 )  -- end x,y

-- with a check-mark near the center.
setPenWidth( Printer, 8 )
drawLine( Printer, halfx-50, halfy+300,
                   halfx, halfy+405 )
setPenWidth( Printer, 12 )
drawArc( Printer, False,
         halfx, halfy+405-600,
         halfx+600, halfy+405+600, 
         halfx+200, halfy-100,
         halfx, halfy+400)

-- then, finally, send the page to the printer
junk=endPage()
-- ending our 'shucks' graphics demonstration.

end if

-- end the document, and,
if endDoc() then
  -- release the printer.
  releasePrinter()
end if
end procedure

--------

onClick[PNow] = routine_id("print_now")

WinMain(PrWin, Normal)

-- end code --

If you study the code, you'll notice that you can send data to the page in any order using setPenPos(). The page is not 'complete' until you send an endPage() command.

The simple 'line-wrap' code formats a line according to the printer's width. This code was originally by David Cuny, as an answer to a mailing list question. It really only works correctly if you are printing fixed-width fonts.

I've just added the bit which tries to remove any space characters from line beginnings, and 'steals' a character from the long line, to maximize the printed line's length.

... anyone who's feeling particularly brave, can try to modify the addressbook examples to use 'just' Win32lib printing functions.

... with knowledge comes success, and with success, comes knowledge...

( or, in programming, ya gotta try things to learn'em ;) )

..end of lesson.

CONTENTS