Print Hints

TRACKING QUICKDRAW GX MESSAGES

PETE ("LUKE") ALEXANDER

In this column, I'd like to bring a tool called MessageWatcher to your attention. This
tool, which is provided on this issue's CD, will help you understand the messages sent
to your QuickDraw GX printer driver or printing extension when an application prints
a document through the QuickDraw GX system.

A LITTLE BACKGROUND
develop Issue 15 gave an overview of QuickDraw GX in the article "Getting Started
With QuickDraw GX" and discussed the QuickDraw GX messaging system in "Developing
QuickDraw GX Printing Extensions." You can also learn about QuickDraw GX printing
and messaging inInside Macintosh: QuickDraw GX Printing Extensions and Drivers . If
you've read these and don't need a refresher, you can just skip to the next section.

QuickDraw GX's extensible printing architecture makes writing printer drivers
easier than ever.   Easier yet is writing printing extensions, which allow you to
modify the behavior of the QuickDraw GX printing system (similar to the way system
extensions let you change the system by patching traps).

When an application prints through the QuickDraw GX system, QuickDraw GX either
performs the requested task or sends a message (via the Message Manager) to the
printer driver to perform the task. The QuickDraw GX printing system defines over
150 messages. For many tasks, QuickDraw GX provides a default implementation for
the associated message, but sends a message to the driver anyway. The driver can then
perform the task in its own way or massage the message parameters before forwarding
the message on to the default implementation. In a printing extension, you can
intercept and override any message before it gets to the printer driver.

ABOUT MESSAGEWATCHER AND OUR EXAMPLE
With over 150 messages in the QuickDraw GX printing system, it's a little difficult to
follow the flow of the messages through the system or figure out their default
implementation. MessageWatcher helps you with this by showing the messages being
sent while an application is printing a document.   This "live" view is very helpful
toward understanding the calling chain and hierarchy of messages.

The MessageWatcher application and system extension are on this issue's CD. To use
MessageWatcher, first drop the system extension into the System Folder and reboot;
then launch the MessageWatcher application. Whenever any application initiates a
print job, a window corresponding to that job will be opened in MessageWatcher and
the messages sent as part of the job will scroll past. The title of each MessageWatcher
window contains the internal ID of the job. (You should view the internal ID of a job
similar to the way you view a file reference number today.)

The QuickDraw GX Finder printing extension (which is part of the QuickDraw GX
system extension) and PrinterShare GX are treated like any other applications
printing through the QuickDraw GX printing system. So they each have a print job
associated with them, andMessageWatcher displays windows for them as well. If you
were to create a desktop printer with the Chooser, there would also be a window for
the Chooser.

As an example, we're going to print a document created and displayed by the "All
Shapes with Printing" sample application, which is part of the sample code included
with QuickDraw GX. This sample creates all of the shapes possible within the graphics
system. Below is the code that prints the page of shapes; keep it in mind while going
through the example of using MessageWatcher in the next section.

OSErr DoPrintOneCopy (WindowPtr myWindow)
{
    Str255windowTitle;
    OSErr printError = noErr;

    if (myWindow)
    {
          GetWTitle(myWindow, windowTitle);
          // Start sending the job. The job has the
          // same name as our window and contains
          // one page. This name appears in the
          // status messages sent to the desktop
          // printer.
          GXStartJob(gDocumentJob, windowTitle, 1);

          // Send the entire page of shapes to the
          // printer. (All the shapes being printed
          // have been collected into the GX picture
          // shape: gthePage.)
          GXPrintPage(gDocumentJob, 1,
                       GXGetJobFormat(gDocumentJob, 1),
                       gthePage);

          // Tell QuickDraw GX printing we're done
          // sending the job, so terminate the
          // spooling process.
          GXFinishJob(gDocumentJob);

          if (GXGetJobError(gDocumentJob) != noErr)
                 // Your error-handling code here!
    }
}

 

We're going to look at our sample application printing to a LaserWriter II SC, so the
message sequence displayed by MessageWatcher contains messages that are sent to a
raster printer. Note that most of the messages would be different if we were printing
to a PostScript® printer or to a plotter.

Each line in a MessageWatcher window consists of a message preceded by one of the
following labels: send message, send object, and send object to. These labels represent
the similarly named API calls in the Message Manager -- for example, "send message"
corresponds to the SendMessage call.   All the "send" labels are roughly equivalent, so
you'll be able to follow along well enough without distinguishing between them; if you
do want more information about the Message Manager calls, see Chapter 6, "Message
Manager," inInside Macintosh: QuickDraw GX Environment and Utilities .

While going through the various MessageWatcher windows in the next section, I won't
bore you with a line-by-line discussion of everything displayed in each window. I'll
give you the general idea behind the information presented; by checking out the
documentation and trying out MessageWatcher yourself on different applications,
you'll be able to figure out these details easily enough.

WHAT MESSAGEWATCHER DISPLAYS
The first time our sample application calls the QuickDraw GX printing API, the
QuickDraw GX Finder printing extension initializes the default printer and then shuts
down. The MessageWatcher window for this extension contains the following (the
window title is shown in boldface; the ID displayed in each title will be different when
you run MessageWatcher yourself):

Finder: 0x0000fac4

send object to: initialize
send object: defaultPrinter
send object to: shutDown

You'll also see PrinterShare GX start up a couple of times: The first time, it performs
some general spool file and desktop printer queue management; it examines all the
spool files and makes sure that the print jobs that are waiting are handled in the
appropriate order. The second time it runs, it starts up the print job. The
MessageWatcher window for PrinterShare GX displays this:

PrinterShare GX: 0x0000fa3c

send object to: initialize
send object: defaultPrinter
send object to: initialize
send object: defaultPrinter
send object: defaultPaperType
send object: defaultFormat
send object: defaultJob
send object: defaultPaperType
send object to: shutDown

Notice that MessageWatcher indents some of information in the window, allowing you
to see the message hierarchy. For example, the above window shows that the recipient
of the defaultJob message sent the message in the indented line below it,
defaultPaperType.

The next application to send messages through the system is our sample application,
All Shapes with Printing. In this case, we chose Print One Copy from the File menu of
the application to start the printing process. The application starts by setting up
various default printing structures associated with the print job.

All Shapes with Printing: 0x00990c

send object to: initialize
send object: defaultPrinter
send object to: initialize
send object: defaultPrinter
send object: defaultPaperType
send object: defaultFormat
send object: defaultJob
    send object: defaultPaperType

Now we'll see the actual messages sent to print a document. Our sample application is
ready to start up the print job and create the spool file. It uses GXPrintPage to print
the document; you'll see the startJob and finishJob messages in the MessageWatcher
window because GXPrintPage sends these messages in its default implementation. Next,
the data contained on the page is spooled to disk.   Finally, the print job is finished, and
the spool file is closed and waiting for PrinterShare GX to find it and send it to the
printer.

send object: startJob
    send message: createSpoolFile
    send object: jobStatus
send object: printPage
    send message: StartPage
          send object: jobStatus
    send message: finishPage
          send message: spoolPage
                 send message: spoolData
                 send message: spoolData
                 send message: spoolData
                 send message: spoolData
                 send message: spoolData
send object: finishJob
    send message: completeSpoolFile
          send object: spoolResource
    send object: jobStatus
send object to: shutDown

The QuickDraw GX printing system is now ready to send the data contained in the spool
file to the printer. PrinterShare GX starts by checking the status of the printer and
then writing (that is, sending) the data. It continues to write the data and check the
device status until all the data is sent.   If a status check were to reveal that an error
had occurred, the error would be available via GXGetJobError to the driver or
extension (not to the application, which is usually out of the printing process at this
point). Once all the data has been sent to the printer, PrinterShare GX checks the
status of the printer one last time, makes sure the print job was successful, closes the
spool file, and shuts down. We now have a piece of paper coming out of the printer.

PrinterShare GX: 0x00092520

send message: getDeviceStatus
send message: writeData
    send message: getDeviceStatus
          lots of writeData and getDeviceStatus
          messages to send the data to the printer
    send message: writeData
    send message: checkStatus
send object: jobStatus
send object: closeSpoolFile
send object to: shutDown

The MessageWatcher window for the QuickDraw GX Finder printing extension shows
the messages it receives to update the status information being displayed in the desktop
printer's window. In this case, the status is updated six times during the process of
printing the document.  To see exactly what status information is being sent to the
desktop printer's window, you could open the window yourself and take a look.
Remember, the messages will be slightly different for different types of printers --
PostScript, raster (QuickDraw based), and plotter.

Finder: 0x000912dc

send object: writeStatusToDTPWindow
send object: writeStatusToDTPWindow
send object: writeStatusToDTPWindow
send object: writeStatusToDTPWindow
send object: writeStatusToDTPWindow
send object: writeStatusToDTPWindow

WATCH OUT NOW . . .
Following the flow of messages through the QuickDraw GX printing system will give
you a better understanding of the calling chain and hierarchy of messages that are sent
while a document is being printed. With MessageWatcher, you have the power to peek
into the world of QuickDraw GX messaging. Happy exploring!

THE RETURN OF 'STR ' (-8192)

In the Print Hints column in Issue 13 of develop , I talked about the disappearance of
'STR ' (-8192) and'PAPA' (-8192) resources from a system running QuickDraw GX
and how your application should be prepared to handle this situation. The 'PAPA'
(-8192) resource is still gone, but the 'STR ' (-8192) resource, containing the
name of the default printer driver, has returned. Unfortunately, there are a few
applications that require this resource to be present to run correctly -- in some
cases, to run at all. Since we wanted old applications to have the highest possible
compatibility while printing through a QuickDraw GX system, we put the resource
back. However, as mentioned in Issue 13, it's still not a good idea to depend on the
information in 'STR ' (-8192).

REFERENCES

PETE ("LUKE") ALEXANDER will tell you that life at Apple is hard. He spends long
days (and frequent nights) with smart people trying to figure out what the right thing
is and how to make it happen. Then he gets sent all over the world to tell people about
what's new and happening. Last year Luke went to London and walked around the streets
for ten hours trying to fend off jet lag and punk rockers, to Madrid where he had an
unforgettable chocolate shake, to Milan where he saw the basement of the Apple
building and tried not to take it personally that they wouldn't let him near a window, to
Munich and Frankfurt where he finally understood why Germans gush about their
beer, and to Sweden where he gave his QuickDraw GX talk in a discotheque filled with
engineers who couldn't get the beat. After these whirlwind tours, Luke soars above the
stress in his glider, but only occasionally takes an Apple Evangelist along, since they
seem to think they've got connections up there and are forever telling him how to fly.
Yes, life at Apple is hard, but after five years, Luke's beginning to get the hang of it. *

Buried deep within QuickDraw GX is an About box. The exercise of how to get to
this box is left for the reader. *

Thanks to Hugo Ayala, Tom Dowdy, and Dave Hersey for reviewing this column. *