
FB II Compiler
PG PRO
Debugging
Memory
System
Mathematics
Resources
Disk I/O
Windows
Controls
Menus
Mouse
Keyboard
Text
Fonts
Drawing
Sound
Clipboard
Printing
Communication
ASM
|
PRINTING
Handle printing
I was talking to Chris Stazny yesterday about Printing stuff. Let me see if I have it right:
1. Always send all pages in your document off to the Print Manager.
The Print Manager is smart enough to extract the correct number of copies of your complete document with the correct page range as read from the standard print dialog.
2. build on the following sequence
DEF LPRINT
LONG IF PRCANCEL = 0
ROUTE _toPrinter 'route drawing to Chooser printer
FN PrintFirstPage
ROUTE _toScreen 'route drawing to Screen
CLEAR LPRINT 'eject first page
ROUTE _toPrinter
FN PrintNthPage
ROUTE _toScreen 'route drawing to Screen
CLEAR LPRINT 'eject nth page
ROUTE _toPrinter
FN PrintLastPage
ROUTE _toScreen
CLOSE LPRINT 'done printing, eject last page, close the printer
END IF
Note that counterintuitively (to me anyhow) ROUTE _toScreen comes before a CLEAR LPRINT or CLOSE LPRINT. (You will also probably need to use a Command Period detection system to abort printing. I have omitted that in the simple example above.)
3. If your document is very complex and certain or all of its pages take a long time to image, it is possible to image only the required page range. Talk to Chris about this.
I have concluded that PowerPC and G3 machines are so fast that the overhead for imaging all pages in a document (leaving it to the Print Manager to decide what to actually print) is, except in very unusual cases, negligible.
I have found this to be true, even when imaging quite large color images.
4) If you try and interpret the print Dialog's page range and/or number of copies yourself and you don't know what you're doing, you end up fighting the Print Manager. The 'fight' can cause seemingly random extra pages and/or copies to be printed.
5) If you are using the PRINT command, always use a semi-colon at the end.
e.g PRINT temp$;
If you are printing at the bottom of your page and you omit the semicolon a <c/r> is appended; this can cause your next print comand to start at the top of a unintended new page....
I always start by using a framed text edit field in my printing so that:
1) I can see the exact box where the text will go.
2) Any text overflow will be masked and not cause an unexpected new page to be printed.
When every thing is OK, I change the framed text edit fields to _noFrame.
6) I achieved a dramatic increase in page construction productivity when the Adobe Acrobat Printer Driver was installed in the Chooser when I installed the Adobe Acrobat Distiller- no more wasted paper and waiting for my very slow printer to output. I estimated that my productivity in this tedious process increased by a factor of at least ten. If you have to design a lot of printer output, I highly recommend the purchase of Distiller just for Chooser acces to the Adobe Acrobat Printer Driver.
I'm not an expert at this and I may have some of it wrong. Any corrections or additions cheerfully accepted...
<< Note that counterintuitively (to me anyhow) ROUTE _toScreen comes before a CLEAR LPRINT or CLOSE LPRINT. >>
In my experience, this is not necessary. I find that this works just as
well:
LONG IF PRCANCEL = 0
ROUTE _toPrinter 'route drawing to Chooser printer
FN PrintFirstPage
CLEAR LPRINT 'eject first page
FN PrintNthPage
CLEAR LPRINT 'eject nth page
FN PrintLastPage
CLOSE LPRINT 'done printing, eject last page;
ROUTE _toScreen
i.e., only one ROUTE _toPrinter and one ROUTE _toScreen are necessary for the entire job, and the ROUTE _toScreen can come after the CLOSE LPRINT. I think it would only be necessary to ROUTE _toScreen during the print job if, for example, you also wanted to send output to a screen window at the same time a print job is progressing. Inter-page rerouting may also be necessary if you need to monitor button clicks & such while the print job is progressing.
Putting CLOSE LPRINT before ROUTE _toScreen, as I've done, may have a drawback--If you do a CLOSE LPRINT, but then the system needs to do something with the "current port" before you do the ROUTE _toScreen, then it may get confused about where exactly the "current port" is. I don't think this should be a problem as long as the two statements appear right next to each other, as in my example.
I must say that I was surprised to find that the Print Manager really does handle "page range" and "number of copies" correctly. I remember older Mac systems in which this wasn't the case--the programmer had to read the Print Record (PRHANDLE), extract the relevant information, and handle the page range & copy count programatically.
Well I did an end run arround the problem I was having with printing. Instead of sending all the print and drawing commands to the printer, I draw into a gWorld and copybits to the printer instead. I was not able to figure out why I could not get printing directly to the printer to work.
What I have is a big image that I want to print. It is much larger that one sheet of paper so I want to print out sheets that tile together.
I have been trying to create the print routine based on this one from the FB handbook examples:
_firstPage = 62 'PRHANDLE field offsets
_lastPage = 64
_copies = 66
LOCAL FN printingRoutine 'this routine handles printing
'
DEF LPRINT 'print... dialog
LONG IF PRCANCEL = _false 'printing cancelled?
WINDOW #2, "", (50,50)-(370,100),_dialogShadow
TEXT _sysFont, 12
msg$ = "To abort printing, hold in the -period keys..."
EDIT FIELD #1,msg$, (10,10)-(310,40),_statNoFramed
gPrtAbort% = _false 'reset abort flag
fromPage% ={[PRHANDLE]+_firstPage} 'get first page to print
toPage% ={[PRHANDLE]+_lastPage} 'get last page to print
copies% ={[PRHANDLE]+_copies} 'get how many copies to print
LONG IF (toPage% <= 0) OR (toPage% => _iPrPgMax)'change 1 to actual pages
toPage% = _iPrPgFst
END IF
ROUTE _toPrinter 'set output to printer
COORDINATE WINDOW '1/72" coordinates for page
pageNum% = 0 'init variable
DO 'print until the last page
INC(pageNum%) 'increment page count
FN checkAbortKeys 'see if cmd-period pressed
LONG IF gPrtAbort% = _false 'only print if abort is false
LONG IF pageNum% => fromPage% 'check if printing in range
FN printPage(pageNum%,copies%) 'call print routine
CLEAR LPRINT 'finish page, go to next page
END IF
END IF
UNTIL pageNum% => toPage% OR gPrtAbort% = _true
ROUTE _toScreen 'set ouput pack to screen
CLOSE LPRINT 'close the printer driver
WINDOW CLOSE #2 'close abort window
EDIT FIELD #2, "Print routine done!", (20,200)-(300,232),_statFramed
END IF
'
END FN
The line that gets the number of copies: "copies% ={[PRHANDLE]+_copies}" always seems to return 1 no matter how many copies are entered in the print dialogue box. Can this FN be replaced by the Print Manager examples above some how?
<< FN printPage(pageNum%,copies%) 'call print routine
CLEAR LPRINT 'finish page, go to next >>
I'm skeptical about this pair of lines. It looks like your intent is to have FN printPage perform the necessary drawing commands a certain number of times (the value of "copies%"), followed by a single call to CLEAR LPRINT after the FN returns. I think you need to call CLEAR LPRINT after _each_ time you draw the page. If copies% = 12, then you should call CLEAR LPRINT 12 times, not once.
<< The line that gets the number of copies: "copies% ={[PRHANDLE]+_copies}" always seems to return 1 no matter how many copies are entered in the print dialogue box. >>
I'm speculating that this is a (relatively) new feature of the system software. Based on a few experiments with new & old Mac's, I _think_ what's happening is this:
In the "old" system software (how old? Don't know) it was the programmer's responsibility to handle page ranges and number-of-copies programatically, by reading those values from the Print Record, and drawing only the appropriate range of pages, and executing a loop, generating the drawing commands repeatedly for the appropriate number of copies.
Nowadays, the system software (or is it just certain printer drivers? I don't know) handle the looping and page-ranging for you. If the user enters "7" in the dialog box, then 7 copies get printed even though your program only executes the drawing commands once. If the user enters "3" as the first page number, then pages 1 and 2 don't get printed, even if your program "tries" to generate them. Using this "new" method, your program should generate the full range of pages, and generate each page only once. The system software will automatically take care of the copies & range that the user requested.
But in order to make this new "automatic" method work with _older_ application software, which is written to loop through copies and to truncate the page range, it's necessary for the system software to "fool" your application. Though the user enters "7" copies, the system only reports "1" to your program. That way, your print loop is fooled into executing only once, and the system will "multiply" that output by 7 for you. (If your loop executed 7 times, the (new) system would print 7 copies for _each_ loop--giving you 49 copies! You don't want that.)
Likewise, my guess is that the newer system "fools" your program into thinking it's supposed to print the entire range of pages, regardless of what the user actually entered in the dialog box. That way, your program merrily generates the entire range, and the system simply ignores the first "n" and the last "m" pages you generate.
|