Moon Travel Planner: Adding Printing to the Moon Facts Window

In Chapter 8 you created the Facts for the Traveler (or moon facts) window to display various information about the moon. To add printing support to the moon facts window, you perform these steps:

  1. Define constants for working with printing.

  2. Define data types for working with printing.

  3. Define prototypes for printing functions.

  4. Write printing functions.

  5. Add a print error format string to the Localizable.strings file.

  6. Add print setup code to the main function.

  7. Adjust code in the moon facts window event handler.

  8. Test the Page Setup and Print commands to prove it all works.

These steps are described in the sections that follow.

Define Constants for Working with Printing

In this section, you’ll define additional constants you’ll need to hook up printing for the moon facts window.

In Chapter 6 you defined the constant kMTPApplicationSignature for the Moon Travel Planner application. In Chapter 8 you defined the constants kMTPPageSetupCommand and kMTPPrintCommand for the Page Setup and Print commands, as well as kMTPMoonFactsTextKey to identify the moon facts window text. You’ll use all these constants in your printing code.

Now you’ll need to define constants to use when you store and retrieve printing information for the moon facts window and when you display printing errors. Copy the following definitions to the main.c file, below the definition for kMTPPrintCommand:

#define kMTPPrintInfoProperty 'Piwp'
#define KMTPPrintFormatStrKey    "Error format"

The constant kMTPPrintInfoProperty includes the word “Property” because you’ll use it to store and retrieve print information as a property of the moon facts window. (The print information structure is described in Section 9.2.2.) You’ll use the constant KMTPPrintFormatStrKey to obtain a localized format string to use when displaying printing errors.

Define Data Types for Working with Printing

In this section, you’ll define a structure for storing print information, as well as pointer and function data types you’ll need for printing.

To print the contents of the moon facts window, you need a convenient way to pass information among your printing functions and in calls to Carbon Printing Manager functions. One such piece of information is a structure to keep track of printing information. You’ll define that structure below, but the C programming language allows you to define a pointer to a structure before defining the structure itself. You’ll do that, because you’ll need the structure pointer for another type defined below. Copy the following type definition to the main.c file, right after the last constant definition:

typedef struct MTPDocumentPrintInfo * MTPDocumentPrintInfoPtr;

You’ll also need a pointer to the function that draws one page of the moon facts window. One of the parameters for the drawing function is a pointer to our print information data structure. That’s why you defined the pointer before the structure. To be able to pass a pointer to a drawing function, copy the following type declaration to the main.c file, right after the previous type definition:

typedef OSStatus (*MTPDrawDocPageProc) 
    (MTPDocumentPrintInfoPtr documentPrintInfoPtr,UInt32 pageNumber);

You’ll see how this pointer type is used in Section 9.2.6, Section 9.2.4.1, and Section 9.2.4.10.

To keep track of printing information, the Moon Travel Planner defines the MTPDocumentPrintInfo structure. Copy the following lines to the main.c file, after the MTPDrawDocPageProc definition:

struct MTPDocumentPrintInfo
{
    PMPrintSession printSession;                          // 1
    
    PMPageFormat pageFormat;                              // 2
    PMPrintSettings printSettings;                        // 3
    
    PMSheetDoneUPP pageSetupDoneUPP;                      // 4
    PMSheetDoneUPP printDialogDoneUPP;                    // 5
    
    MTPDrawDocPageProc drawDocPageProc;                   // 6
};
typedef struct MTPDocumentPrintInfo MTPDocumentPrintInfo; // 7

This structure provides the following fields:

  1. A printing session to use for all moon facts printing. PMPrintSession is an opaque data structure defined by the Carbon Printing Manager.

  2. A page format object to track format information, such as paper size and orientation. PMPageFormat is an opaque data structure defined by the Carbon Printing Manager.

  3. A print settings object to track settings information, such as page range and number of copies. PMPrintSettings is an opaque data structure defined by the Carbon Printing Manager.

  4. A pointer to a function the Carbon Printing Manager calls when the user closes the Page Setup dialog.

  5. A pointer to a function the Carbon Printing Manager calls when the user closes the Print dialog.

  6. A pointer to a function that draws one page of the moon facts window. The definition for the pointer type (MTPDrawDocPageProc) is shown above.

  7. The last item is not a field of the structure, but merely a type definition for the structure itself.

You’ll learn how to initialize this data structure in the MTPCreatePrintInfoForWindow function.

Define Prototypes for Printing Functions

In this section you’ll define function prototypes for the Moon Travel Planner’s printing functions. Copy the following lines to the main.c file, right after the function prototypes for window event and command handler functions:

OSStatus MTPCreatePrintInfoForWindow (
                WindowRef theWindow,
                MTPDrawDocPageProc drawDocPageProc,
                PMSheetDoneUPP pageSetupDoneProc,
                PMSheetDoneUPP printDialogDoneProc);
OSStatus MTPSetupPageFormatForPrinting(
                MTPDocumentPrintInfoPtr documentPrintInfoPtr);
pascal void MTPPageSetupDoneProc (
                PMPrintSession printSession,
                WindowRef documentWindow,
                Boolean accepted);
void MTPDoPageSetup (WindowRef parentWindow);
pascal void MTPPrintDialogDoneProc (
                PMPrintSession printSession, 
                WindowRef documentWindow, 
                Boolean accepted);
void MTPDoPrint ( WindowRef parentWindow );
OSStatus MTPDrawMoonFactsPage (
                    MTPDocumentPrintInfoPtr documentPrintInfoPtr,
                    UInt32 pageNumber);
UInt32    MTPPagesInDoc (MTPDocumentPrintInfoPtr documentPrintInfoPtr); 
void MTPPostPrintingError (OSStatus status);
void MTPDoPrintLoop (MTPDocumentPrintInfoPtr documentPrintInfoPtr);

These functions are described in the following section.

Write Printing Functions

It’s time to write printing code for the Moon Travel Planner application. It may seem like you need a lot of functions to print some simple text, but the printing code in this chapter provides several benefits:

  • It demonstrates a variety of printing concepts, including how to display the Page Setup and Print dialogs and how to set up a print loop to print each page in a document.

  • It supports the really cool Mac OS X feature of sheets—the Page Setup and Print dialogs appear as sheets that pop out of the title bar of the moon facts window. A sheet is part of the window it appears on, providing a convenient way to associate a dialog with a window.

  • It provides a reusable template that you can easily adapt to print other, more complicated documents.

To print the text from the moon facts window, you’ll need to create the following functions:

  1. MTPCreatePrintInfoForWindow. Initializes a print data structure and stores it with the window to print.

  2. MTPSetupPageFormatForPrinting. Prepares a valid page format object for use with page setup or printing and creates a print session object.

  3. MTPPageSetupDoneProc. Called by the Carbon Printing Manager when the user dismisses the Page Setup dialog, regardless of whether the user accepted the dialog or canceled it.

  4. MTPDoPageSetup. Displays the Page Setup dialog (shown in Figure 9.1).

  5. MTPPrintDialogDoneProc. Called by the Carbon Printing Manager when the user dismisses the Print dialog, regardless of whether the user accepted the dialog or canceled it.

  6. MTPDoPrint. Displays the Print dialog (shown in Figure 9.2).

  7. MTPDrawMoonFactsPage. Draws the specified page in the location specified by the page format object.

  8. MTPPagesInDoc. Returns the maximum number of pages to print in the document.

  9. MTPPostPrintingErrors. Displays an alert to notify the user that a printing error has occurred.

  10. MTPDoPrintLoop. Loops over the specified page range, calling the draw page routine for each page.

The next sections describe the code for these functions.

MTPCreatePrintInfoForWindow

The MTPCreatePrintInfoForWindow function initializes a print data structure and stores it with the window to print (in this case, the moon facts window). Copy the code shown in Example 9.1 to the main.c file, below the MTPAboutWindowCommandHandler function.

Example 9-1. A Function to Create Print Information for a Window

OSStatus MTPCreatePrintInfoForWindow (
                        WindowRef theWindow,
                        MTPDrawDocPageProc drawDocPageProc,
                        PMSheetDoneUPP pageSetupDoneProc,
                        PMSheetDoneUPP printDialogDoneProc)
{
    MTPDocumentPrintInfoPtr documentPrintInfoPtr = NULL;
    OSStatus status = noErr;

    documentPrintInfoPtr = 
        (MTPDocumentPrintInfoPtr) NewPtr(sizeof(MTPDocumentPrintInfo));// 1

    if (documentPrintInfoPtr)                                          // 2
    {
        documentPrintInfoPtr->printSession = NULL;                     // 3
        documentPrintInfoPtr->pageSetupDoneUPP = pageSetupDoneProc;    // 4
        documentPrintInfoPtr->printDialogDoneUPP = printDialogDoneProc;// 5
        documentPrintInfoPtr->drawDocPageProc = drawDocPageProc;       // 6
        documentPrintInfoPtr->pageFormat = kPMNoPageFormat;            // 7
        documentPrintInfoPtr->printSettings = kPMNoPrintSettings;      // 8

        status = SetWindowProperty(theWindow, kMTPApplicationSignature,// 9
                        kMTPPrintInfoProperty,
                        sizeof(MTPDocumentPrintInfoPtr), 
                        &documentPrintInfoPtr);
    }
    else
        status = MemError();                                          // 10
        
    if ((status != noErr) && (documentPrintInfoPtr != NULL))          // 11
        DisposePtr( (Ptr) documentPrintInfoPtr);

    return status;                                                    // 12

}

Here’s how the MTPCreatePrintInfoForWindow function works:

  1. It calls the Memory Manager function NewPtr to allocate memory for a print information structure. If the call is successful, the pointer documentPrintInfoPtr points to the allocated memory.

  2. If the previous step was successful, it sets values for the print information structure.

  3. It sets the printing session reference to NULL, indicating the object hasn’t been created yet. This object won’t be created until it is needed—when the user opens the Page Setup or Print dialog.

  4. It stores a reference to a function the Carbon Printing Manager calls when the user dismisses the Page Setup dialog. The reference comes from the pageSetupDoneProc parameter.

  5. It stores a reference to a function the Carbon Printing Manager calls when the user dismisses the Print dialog. The reference comes from the printDialogDoneProc parameter.

  6. It stores a reference to a function the Moon Travel Planner’s MTPDoPrintLoop function calls to print a single page. The reference comes from the drawDocPageProc parameter.

  7. It sets the page format reference to a value that indicates the page format object hasn’t been created yet. This object won’t be created until it is needed—when the user opens the Page Setup or Print dialog.

  8. It sets the print settings reference to a value that indicates the print settings object hasn’t been created yet. This object won’t be created until it is needed—when the user opens the Print dialog.

  9. It calls the Window Manager function SetWindowProperty to store a pointer to the print information structure as a property of the window. The constants kMTPApplicationSignature and kMTPPrintInfoProperty identify the property, which other printing functions can access by calling the Window Manager function GetWindowProperty. These constants are described in Section 9.2.1.

  10. If it couldn’t create the print information structure by calling NewPtr, it calls the function MemError, which yields the result code produced by the last Memory Manager function the application called directly (NewPtr).

  11. If there was an error after allocating the print information structure, MTPDoPageSetup calls the Memory Manager function DisposePtr to dispose of the allocated memory.

  12. It returns a value indicating whether the function successfully created and initialized a print information structure for the window. A return value of noErr indicates success.

MTPSetupPageFormatForPrinting

The MTPSetupPageFormatForPrinting function prepares a valid page format object for use with the Page Setup or Print dialog. Both of those dialogs require a printing session object, so the function also creates a printing session object, though it is possible to create a page format object without a printing session. If any error occurs before the function completes, it frees any objects it created.

Copy the code shown in Example 9.2 to the main.c file, below the MTPCreatePrintInfoForWindow function.

Example 9-2. A Function to Set Up a Page Format Object for Printing

OSStatus MTPSetupPageFormatForPrinting(
                MTPDocumentPrintInfoPtr documentPrintInfoPtr)
{
    OSStatus status = noErr;
    PMPrintSession printSession = NULL;
    PMPageFormat pageFormat = kPMNoPageFormat;
    
    status = PMCreateSession(&printSession);                           // 1
    if (status == noErr)
    {
        if (documentPrintInfoPtr->pageFormat == kPMNoPageFormat)       // 2
        {
            status = PMCreatePageFormat(&pageFormat);                  // 3
            if ((status == noErr) && (pageFormat != kPMNoPageFormat))
            {
                status = PMSessionDefaultPageFormat(                   // 4
                            printSession,
                            pageFormat);
                if (status == noErr)
                    documentPrintInfoPtr->pageFormat = pageFormat;     // 5
            }
            else 
            {
                if (status == noErr)                                   // 6
                    status = kPMGeneralError;
            }
        }
        else
        {
            status = PMSessionValidatePageFormat(                      // 7
                        printSession,
                        documentPrintInfoPtr->pageFormat,
                        kPMDontWantBoolean);
        }
    }
    if (status == noErr)
    {
        documentPrintInfoPtr->printSession = printSession;             // 8
    }
    else                                                               // 9
    {
        if (pageFormat != kPMNoPageFormat)
            PMRelease(pageFormat);
        if (printSession != NULL)
            PMRelease(printSession);
    }
    return status;
}

Here’s how the MTPSetupPageFormatForPrinting function works:

  1. It calls the Carbon Printing Manager (CPM) function PMCreateSession to create a printing session object.

  2. If the previous step succeeds, it checks whether the print information structure pointed to by the documentPrintInfoPtr parameter already has a reference to a page format object. The constant kPMNoPageFormat is defined by the Carbon Printing Manager to specify that a page format object (one of type PMPageFormat) has not yet been specified.

  3. If no format object exists, it calls the CPM function PMCreatePageFormat to create a page format object.

  4. If no error occurred in creating the page format object, it calls the CPM function PMSessionDefaultPageFormat to set default values (such as 100 percent scaling and portrait orientation) for a page format object.

  5. If no error occurs in setting default values, it assigns the page format object to the page format field in the print information structure pointed to by the documentPrintInfoPtr parameter.

  6. If the function PMCreatePageFormat didn’t return an error in step 3, but was unable to create a page format object, MTPSetupPageFormatForPrinting uses the CPM constant kPMGeneralError to set an error value.

  7. If the print information structure pointed to by the passed pointer already has a reference to a page format object, MTPSetupPageFormatForPrinting calls the CPM function PMSessionValidatePageFormat to make sure the page format object is valid within the context of the current printing session.

  8. If no error has occurred, it assigns the printing session object to the printing session field in the print information structure pointed to by the documentPrintInfoPtr parameter.

  9. If any error has occurred, it releases any local variables it may have created (a printing session object and possibly a page format object).

  10. It returns a value indicating whether the function successfully created and initialized a printing session object and prepared a page format object (creating it if necessary). A return value of noErr indicates success.

MTPPageSetupDoneProc

The Carbon Printing Manager calls the MTPPageSetupDoneProc function when the user dismisses the Page Setup dialog, regardless of whether the user accepted the dialog or canceled it. This function merely frees the current printing session object, which needn’t be saved after the user dismisses the Page Setup dialog. However, applications with more complicated printing needs may wish to perform other operations here. For example, an application may wish to change the displayed margins when a user changes the paper size in the Page Setup dialog.

Copy the code shown in Example 9.3 to the main.c file, below the MTPSetupPageFormatForPrinting function.

Example 9-3. Function Called When Page Setup Dialog Is Dismissed

pascal void MTPPageSetupDoneProc (
                    PMPrintSession printSession, 
                    WindowRef documentWindow, 
                    Boolean accepted)
{
    OSStatus    status = noErr;                                      // 1
    UInt32    infoSize = sizeof (MTPDocumentPrintInfoPtr), 
              actualSize;
    MTPDocumentPrintInfoPtr documentPrintInfoPtr = NULL;
    
    status = GetWindowProperty(documentWindow,                       // 2
                kMTPApplicationSignature,
                kMTPPrintInfoProperty, 
                infoSize, &actualSize, 
                &documentPrintInfoPtr);
                
    if ((status == noErr) && (documentPrintInfoPtr != NULL))         // 3
    {
        if (documentPrintInfoPtr->printSession != NULL)
        {
            PMRelease(documentPrintInfoPtr->printSession);
            documentPrintInfoPtr->printSession = NULL;
        }
    }
}

Here’s how the MTPPageSetupDoneProc function works:

  1. It declares and initializes local variables for getting stored print information from the passed window.

  2. It calls the Window Manager function GetWindowProperty, passing the constants kMTPApplicationSignature and kMTPPrintInfoProperty to specify the window property to retrieve (a pointer to a Moon Travel Planner print information structure).

  3. If it can get a pointer to the print info structure and if the printing session field in the structure is not NULL, it releases the printing session object and sets the field to NULL.

MTPDoPageSetup

The MTPDoPageSetup function displays the Page Setup dialog (shown in Figure 9.1) so the user can specify settings such as paper size and orientation.

Copy the code shown in Example 9.4 to the main.c file, below the MTPPageSetupDoneProc function.

Example 9-4. The Page Setup Function

void MTPDoPageSetup( WindowRef parentWindow )
{
    OSStatus status = noErr;                                         // 1
    UInt32 infoSize = sizeof (MTPDocumentPrintInfoPtr), actualSize;
    MTPDocumentPrintInfoPtr documentPrintInfoPtr = NULL;
    
    status = GetWindowProperty(parentWindow,                         // 2
                kMTPApplicationSignature,
                kMTPPrintInfoProperty, 
                infoSize, &actualSize, 
                &documentPrintInfoPtr);
                
    if ((status == noErr) && (documentPrintInfoPtr != NULL))         // 3
    {
        status = MTPSetupPageFormatForPrinting(                      // 4
                             documentPrintInfoPtr);
        if (status == noErr)
        {
            Boolean accepted;
            PMSessionUseSheets (                                     // 5
                    documentPrintInfoPtr->printSession, parentWindow, 
                    documentPrintInfoPtr->pageSetupDoneUPP);
            
            status = PMSessionPageSetupDialog(                       // 6
                    documentPrintInfoPtr->printSession, 
                    documentPrintInfoPtr->pageFormat, &accepted);
        }
    }
    else if (status == noErr)                                        // 7
        status = memFullErr;
    if (status != noErr)                                             // 8
    {
        if (documentPrintInfoPtr != NULL)
        {
            if (documentPrintInfoPtr->printSession != NULL)          // 9
            {
                PMRelease(documentPrintInfoPtr->printSession);
                documentPrintInfoPtr->printSession = NULL;
            }
        }
        MTPPostPrintingError(status);                                // 10
    }
}

Here’s how the MTPDoPageSetup function works:

  1. It declares and initializes local variables for getting stored print information from the passed window.

  2. It calls the Window Manager function GetWindowProperty, passing the constants kMTPApplicationSignature and kMTPPrintInfoProperty to specify the window property to retrieve (a pointer to a Moon Travel Planner print information structure).

  3. It verifies that GetWindowProperty returned a non-null pointer to a print information structure.

  4. It calls the function MTPSetupPageFormatForPrinting to make sure the print information includes a valid page format object. This function also creates a printing session object for the print information pointer.

  5. If no error occurs, it calls the Carbon Printing Manager function PMSessionUseSheets, passing the current printing session, the window to be printed, and a pointer to a function the Printing Manager calls when the user dismisses the Page Setup dialog. The pointer points to the MTPPageSetupDoneProc function. Calling the PMSessionUseSheets function specifies that a printing dialog (in this case the Page Setup dialog) should be displayed as a sheet; that is, attached to the window of the document being printed.

  6. To display the Page Setup dialog, it calls the Carbon Printing Manager function PMSessionPageSetupDialog, passing the current printing session, the page format object that was set up in a previous step, and a pointer to a Boolean value. When the user dismisses the Page Setup dialog, the Printing Manager calls the function specified by documentPrintInfoPtr->pageSetupDoneUPP in the previous call to PMSessionUseSheets. When using sheets, the PMSessionPageSetupDialog function returns immediately and the Boolean value returned in the accepted variable always has the value false. If your application needs to perform additional tasks after the user dismisses the Page Setup dialog, it can do so in the MTPPageSetupDoneProc function, which is called when the user dismisses the Page Setup dialog. If the user clicks the OK button in the Page Setup dialog, the page format object is updated with the user’s changes (if any) and the value true is returned to the MTPPageSetupDoneProc function. If the user clicks the Cancel button, the page format object is unchanged and the value false is returned to the MTPPageSetupDoneProc function.

  7. If the previous call to GetWindowProperty was unsuccessful in creating a pointer to a print information structure, but did not return an error value, MTPDoPageSetup sets an error value.

  8. It checks the status variable—if there is an error, the Page Setup dialog was not displayed. The MTPDoPageSetup function will display an error message and may have some cleaning up to do as well.

  9. If an error occurred after getting a pointer to a print information structure and the structure has a pointer to a session object, it releases the object and sets the pointer to NULL.

  10. It displays an error message to the user.

MTPPrintDialogDoneProc

The Carbon Printing Manager calls the MTPPrintDialogDoneProc function when the user dismisses the Print dialog, regardless of whether the user accepts the dialog or cancels it. This function initiates printing if the user accepted the Print dialog and frees the printing session and print settings object if the user canceled the dialog.

Copy the code shown in Example 9.5 to the main.c file, below the MTPDoPageSetup function.

Example 9-5. Function Called When Print Dialog Is Dismissed

pascal void MTPPrintDialogDoneProc (PMPrintSession printSession,
    WindowRef documentWindow, Boolean accepted)
{
    OSStatus    status = noErr;                                  // 1
    UInt32    infoSize = sizeof (MTPDocumentPrintInfoPtr), 
              actualSize;
    MTPDocumentPrintInfoPtr documentPrintInfoPtr = NULL;
    
    status = GetWindowProperty(documentWindow,                   // 2
                kMTPApplicationSignature,
                kMTPPrintInfoProperty, 
                infoSize, &actualSize, 
                &documentPrintInfoPtr);
    
    if ((status == noErr) && (documentPrintInfoPtr != NULL))
    {
        if (accepted)
            MTPDoPrintLoop(documentPrintInfoPtr);                // 3
        else
        {
            if (documentPrintInfoPtr->printSettings              // 4
                              != kPMNoPrintSettings)
            {
                PMRelease(documentPrintInfoPtr->printSettings);
                documentPrintInfoPtr->printSettings = kPMNoPrintSettings;
            }
            if (documentPrintInfoPtr->printSession != NULL)
            {
                PMRelease(documentPrintInfoPtr->printSession);
                documentPrintInfoPtr->printSession = NULL;
            }
        }
    }
}

Here’s how the MTPPrintDialogDoneProc function works:

  1. It declares and initializes local variables for getting stored print information from the passed window.

  2. It calls the Window Manager function GetWindowProperty, passing the constants kMTPApplicationSignature and kMTPPrintInfoProperty to specify the window property to retrieve (a pointer to a Moon Travel Planner print information structure).

  3. If step 2 succeeded and the user accepted the Print dialog (accepted has the value true), MTPPrintDialogDoneProc calls the MTPDoPrintLoop function to print each page in the selected range. Applications with more complicated printing needs can perform additional operations before commencing printing.

  4. If step 2 succeeded and the user canceled the Print dialog (accepted has the value false), MTPPrintDialogDoneProc calls the Carbon Printing Manager function PMRelease to release the print information structure’s printing session object and print settings object, if any, and sets the fields for these objects to values indicating they are no longer valid. Releasing an object decrements its reference count, causing it to be deallocated when the count reaches 0. Other applications may need to perform additional operations here in the case that the user cancels the dialog.

MTPDoPrint

The MTPDoPrint function displays the Print dialog (shown in Figure 9.2) so the user can specify such settings as page range and number of copies before printing.

Copy the code shown in Example 9.6 to the main.c file, below the MTPPrintDialogDoneProc function.

Example 9-6. The Print Function

void MTPDoPrint( WindowRef parentWindow )
{
    PMPrintSettings printSettings = kPMNoPrintSettings;
    UInt32    minPage = 1,
              maxPage = 1;
    OSStatus status = noErr;                                            // 1
    UInt32 infoSize = sizeof (MTPDocumentPrintInfoPtr), actualSize;
    MTPDocumentPrintInfoPtr documentPrintInfoPtr = NULL;
    
    status = GetWindowProperty( parentWindow,                           // 2
                                kMTPApplicationSignature, 
                                kMTPPrintInfoProperty, 
                                infoSize,
                                &actualSize, 
                                &documentPrintInfoPtr);

    if ((status == noErr) && (documentPrintInfoPtr != NULL))
    {
        status = MTPSetupPageFormatForPrinting(documentPrintInfoPtr);   // 3
        if (status == noErr)
        {
            status = PMCreatePrintSettings(&printSettings);             // 4
            
            if ((status == noErr) && (printSettings != kPMNoPrintSettings))
            {
                CFStringRef windowTitleRef;
                status = CopyWindowTitleAsCFString(parentWindow,        // 5
                                &windowTitleRef);
                if(status == noErr)
                {
                    status = PMSetJobNameCFString(printSettings,        // 6
                                windowTitleRef);
                    CFRelease(windowTitleRef);
                }
                if (status == noErr)
                    status = PMSessionDefaultPrintSettings(             // 7
                                documentPrintInfoPtr->printSession,
                                printSettings);
                if (status == noErr) 
                {
                    documentPrintInfoPtr->printSettings = printSettings;// 8
                    printSettings = kPMNoPrintSettings;
                }
            }
            if (status == noErr)
            {
                maxPage = MTPPagesInDoc(documentPrintInfoPtr);          // 9
                status = 
                    PMSetPageRange(documentPrintInfoPtr->printSettings, // 10
                                       minPage, maxPage);
            }

            if (status == noErr)
            {
                Boolean accepted;
                PMSessionUseSheets (                                    // 11
                                documentPrintInfoPtr->printSession, 
                                parentWindow,
                                documentPrintInfoPtr->printDialogDoneUPP);
    
                status = PMSessionPrintDialog(                          // 12
                            documentPrintInfoPtr->printSession,
                            documentPrintInfoPtr->printSettings,
                            documentPrintInfoPtr->pageFormat,
                            &accepted);
            }
        }
    }
    else
    {
        if (status == noErr)                                           // 13
            status = memFullErr;
    }
    if (status != noErr)                                               // 14
    {
        if (documentPrintInfoPtr != NULL)
        {
            if (printSettings != kPMNoPrintSettings)                   // 15
                PMRelease(printSettings);
            else if (documentPrintInfoPtr->printSettings               // 16
                                   != kPMNoPrintSettings)
            {
                PMRelease(documentPrintInfoPtr->printSettings);
                documentPrintInfoPtr->printSettings = kPMNoPrintSettings;
            }
            if (documentPrintInfoPtr->printSession != NULL)            // 17
            {
                PMRelease(documentPrintInfoPtr->printSession);
                documentPrintInfoPtr->printSession = NULL;
            }
        }
        MTPPostPrintingError(status);                                  // 18
    }
}

Here’s how the MTPDoPrint function works:

  1. It declares and initializes local variables for getting stored print information from the passed window.

  2. It calls the Window Manager function GetWindowProperty, passing the constants kMTPApplicationSignature and kMTPPrintInfoProperty to specify the window property to retrieve (a pointer to a Moon Travel Planner print information structure).

  3. If GetWindowProperty successfully returns a valid pointer to a print information structure, MTPDoPrint calls the MTPSetupPageFormatForPrinting function to make sure the print information structure has a valid page format object for this printing session. That function also creates a printing session object for the session.

  4. If no error occurs, it calls the Carbon Printing Manager (CPM) function PMCreatePrintSettings to create a print settings object for this print job. By not saving print settings between calls to the Print dialog, you ensure that the dialog will display with the current default settings, which is the recommended behavior.

  5. If no error occurs, it calls the Core Foundation function CopyWindowTitleAsCFString to get the window title as a CFStringRef (or reference to a string object).

  6. If no error occurs, it calls the CPM function PMSetJobNameCFString to set the job name for this print job. This is the name that will be used by the printing system, such as in the print queue. After setting the title, it calls the Core Foundation function CFRelease to release the string.

  7. If no error occurs in the previous step, it calls the CPM function PMSessionDefaultPrintSettings to set default values (such as printer, number of copies, and page range) for the print settings object.

  8. If no error occurs in the previous step, it assigns the print settings object to the print settings field in the print information structure and sets the local settings variable to a value indicating it is no longer in use.

  9. It calls the function MTPPagesInDoc so the Moon Travel Planner can specify the maximum number of pages to print.

  10. It calls the CPM function PMSetPageRange to set the valid range of pages that can be printed.

  11. If no error has occurred, it calls the CPM function PMSessionUseSheets, passing the current printing session, a reference to the window to be printed, and a pointer to a function the Carbon Printing Manager calls when the user dismisses the Print dialog. The pointer points to the MTPPrintDialogDoneProc function. Calling the PMSessionUseSheets function specifies that a printing dialog (in this case the Print dialog) should be displayed as a sheet; that is, attached to the window of the document being printed.

  12. To display the Print dialog, MTPDoPrint calls the CPM function PMSessionPrintDialog, passing the current printing session, the print settings object, the page format object, and a pointer to a Boolean value. When the user dismisses the Print dialog, the Carbon Printing Manager calls the function specified by documentPrintInfoPtr->printDialogDoneUPP in the previous call to PMSessionUseSheets (in this case, MTPPrintDialogDoneProc, which takes care of printing the page if the user accepts the dialog). When using sheets, the PMSessionPrintDialog function returns immediately and the Boolean value returned in the accepted variable always has the value false. If your application needs to perform additional tasks after the user dismisses the Print dialog, it can do so in the MTPPrintDialogDoneProc function. If the user clicks the OK button in the Print dialog, the print settings object is updated with the user’s changes (if any) and the value true is returned to the MTPPrintDialogDoneProc function. If the user clicks the Cancel button, the print settings object is unchanged and the value false is returned to the MTPPrintDialogDoneProc function.

  13. If the earlier call to GetWindowProperty was unsuccessful in creating a pointer to a print information structure, but did not return an error value, MTPDoPrint sets an error value.

  14. It checks for any error. At this point, if an error has occurred, you know the Print dialog was never displayed. If an error occurred after getting a pointer to a print information structure, you may have some cleaning up to do—otherwise, you’ll just display the error number.

  15. If the local print settings variable has a reference to a print settings object, MTPDoPrint calls the CPM function PMRelease to release it. Releasing an object decrements its reference count, causing it to be deallocated when the count reaches 0.

  16. If the print information structure has a print settings object, MTPDoPrint calls the CPM function PMRelease to release it and sets the field for this object to a value indicating it is no longer valid.

  17. If the print information structure has a printing session object, MTPDoPrint calls the CPM function PMRelease to release it and sets the field for this object to a value indicating it is no longer valid.

  18. It calls the function MTPPostPrintingError to display the error to the user.

MTPDrawMoonFactsPage

The MTPDrawMoonFactsPage function draws the specified page in the location specified by the page format object. Copy the code shown in Example 9.7 to the main.c file, below the MTPDoPrint function.

Example 9-7. Function to Draw One Page of the Moon Facts Window

OSStatus MTPDrawMoonFactsPage(
    MTPDocumentPrintInfoPtr documentPrintInfoPtr, UInt32 pageNumber)
{
    OSStatus    status = noErr;
    Rect bounds;
    CFStringRef text;
    PMRect   pageRect;
    
    status = PMGetAdjustedPageRect(
                    documentPrintInfoPtr->pageFormat, &pageRect);      // 1
    if (status == noErr)
    {
        text = CFCopyLocalizedString(CFSTR(kMTPMoonFactsTextKey),NULL);// 2
        
        if (text != NULL)
        {
            SetRect(&bounds, pageRect.left, pageRect.top,              // 3
                            pageRect.right, pageRect.bottom);
        
            TXNDrawCFStringTextBox (text, &bounds, NULL, NULL);        // 4
            CFRelease(text);                                           // 5
        }
        else
            status = coreFoundationUnknownErr;                         // 6
    }
    
    return status;                                                     // 7
    
}

Here’s how the MTPDrawMoonFactsPage function works:

  1. It calls the Carbon Printing Manager function PMGetAdjustedPageRect to obtain the page size (the imageable area), in points, taking into account orientation, application drawing resolution, and scaling settings.

  2. It calls the Core Foundation string function CFCopyLocalizedString to get the text that is displayed in the moon facts window.

  3. If no error occurs, it sets a drawing location using the previously obtained page size information. This sample code sticks to printing one page, so it always prints the same text regardless of the specified page number. Applications that print more complicated documents would determine the correct material to print for the specified page.

  4. It calls the Multilingual Text Engine (MLTE) function TXNDrawCFStringTextBox to draw the text from the moon facts window in the specified rectangle.

  5. It calls the Core Foundation function CFRelease to release the string created by the call to CFCopyLocalizedString.

  6. If it was unable to obtain the text string in the previous call to CFCopyLocalizedString, it sets an error value, using the constant coreFoundationUnknownErr (for an unknown Core Foundation error).

  7. It returns a status value, indicating whether it succeeded in drawing the page.

The moon facts window has very simple printing needs and only draws one page of text. More complex applications are likely to require more complex drawing and page range calculations. Related issues are described in the next section on the MTPPagesInDoc function.

MTPPagesInDoc

The MTPPagesInDoc function returns the maximum number of pages to print in the document. Copy the code shown in Example 9.8 to the main.c file, below the MTPDrawMoonFactsPage function.

Example 9-8. A Function to Supply the Number of Pages in a Document

UInt32    MTPPagesInDoc(MTPDocumentPrintInfoPtr documentPrintInfoPtr) 
{
    PMRect   paperRect, pageRect;
    UInt32   numPages = 1;
    OSStatus status = noErr;
    
    status = PMGetAdjustedPaperRect(
                    documentPrintInfoPtr->pageFormat, &paperRect);// 1
    if (status == noErr)
    {
        status = PMGetAdjustedPageRect(
                    documentPrintInfoPtr->pageFormat, &pageRect); // 2
        if (status == noErr)
            numPages = 1;                                         // 3
    }
    return numPages;                                              // 4
}

Here’s how the MTPPagesInDoc function works:

  1. It calls the Carbon Printing Manager (CPM) function PMGetAdjustedPaperRect to obtain the paper size, taking into account orientation, application drawing resolution, and scaling settings. Applications that print more complicated documents could use this information in determining the number of pages in the document based on the current print settings.

  2. If no error occurred, it calls the CPM function PMGetAdjustedPageRect to obtain the page size (the imageable area), in points, taking into account orientation, application drawing resolution, and scaling settings. Again, some applications may need to use this information to compute the number of pages in the document.

  3. If no error occurred, it sets a hard-coded value of one for the number of pages. For most applications, your page count may vary.

  4. It returns the computed number of pages to print in the document.

Of course, most applications will need to do more work than shown here. The number of pages in a document is likely to depend on a number of factors, including document-specific changes by the user (such as adding text or changing font size), as well as Page Setup and Print dialog settings. Some applications might require a separate version of this function for each kind of document they print. If so, you might add a field to the print information structure (described in Section 9.2.2) to specify the page count function to be called from the main printing function (in this case, MTPDoPrint).

MTPPostPrintingErrors

The MTPPostPrintingErrors function displays an alert to notify the user that a printing error has occurred. The alert message includes a localized string and the error number. Copy the code shown in Example 9.9 to the main.c file, below the MTPPagesInDoc function.

Example 9-9. A Function to Post a Printing Error Alert

void     MTPPostPrintingError(OSStatus status)
{
    CFStringRef formatStr = NULL, printErrorMsg = NULL;
    SInt16      alertItemHit = 0;
    Str255      stringBuf;

    // Display any error except user cancelled.
    if ((status != noErr) && (status != kPMCancel))           // 1
    {
        formatStr =  CFCopyLocalizedString(                   // 2
                         CFSTR(KMTPPrintFormatStrKey), NULL);
        if (formatStr != NULL)
        {
            printErrorMsg = CFStringCreateWithFormat(         // 3
                       NULL, NULL, 
                       formatStr, status);
            if (printErrorMsg != NULL)
            {
                if (CFStringGetPascalString(printErrorMsg,    // 4
                              stringBuf, sizeof(stringBuf), 
                              kCFStringEncodingASCII))
                    StandardAlert(kAlertStopAlert, stringBuf, // 5
                                NULL, NULL, &alertItemHit);
                CFRelease(printErrorMsg);                     // 6
            }
           CFRelease(formatStr);                              // 7
        }
    }
}

Here’s how the MTPPostPrintingErrors function works:

  1. It checks whether the passed error should be displayed. Any error except kPMCancel, indicating the user cancelled printing, should be displayed.

  2. It calls the Core Foundation string function CFCopyLocalizedString to get a localized formatting string that indicates how the error should be formatted for display.

  3. If no error occurs, it calls the Core Foundation string function CFStringCreateWithFormat to get a copy of the string that includes the error number.

  4. If no error occurs, it calls the Core Foundation string function CFStringGetPascalString to get a copy of the string that it can display in a standard alert dialog.

  5. It calls the Carbon function StandardAlert to display the error message, including the error number.

  6. It calls the Core Foundation function CFRelease to release the string (printErrorMsg) created by the call to CFCopyLocalizedString.

  7. It calls the Core Foundation function CFRelease to release the string (formatStr) created by the call to CFStringCreateWithFormat.

MTPDoPrintLoop

The MTPDoPrintLoop function loops over the specified page range, calling your draw page function for each page. This function is the Saturn V rocket of printing functions—it does a lot of heavy lifting. But because it does most of its work by calling Carbon Printing Manager functions, passing information obtained from a document print information structure you defined, you should be able to adapt this print loop code for applications with more sophisticated printing requirements.

Copy the code shown in Example 9.10 into the main.c file, below the MTPPostPrintingErrors function.

Example 9-10. A Print Loop Function

void MTPDoPrintLoop(MTPDocumentPrintInfoPtr documentPrintInfoPtr)
{
    OSStatus status = noErr,
             tempErr = noErr;
    UInt32   realNumberOfPagesinDoc, pageNumber, firstPage, lastPage;
    GrafPtr  currentPort, printingPort;
               
    realNumberOfPagesinDoc = MTPPagesInDoc(documentPrintInfoPtr);  // 1

    status = PMGetFirstPage(
                documentPrintInfoPtr->printSettings, &firstPage);  // 2
                
    if (status == noErr)
        status = PMGetLastPage(
                documentPrintInfoPtr->printSettings, &lastPage);   // 3

    if (status == noErr)
    {
        if (realNumberOfPagesinDoc < lastPage)                     // 4
            lastPage = realNumberOfPagesinDoc;
            
        status = PMSetFirstPage(                                   // 5
                     documentPrintInfoPtr->printSettings, 
                     firstPage, false);
        if (status == noErr)
            status = PMSetLastPage(                                // 6
                        documentPrintInfoPtr->printSettings, 
                        lastPage, false);
    }
    if (status == noErr)
    {
        status = PMSessionBeginDocument(                           // 7
                    documentPrintInfoPtr->printSession, 
                    documentPrintInfoPtr->printSettings, 
                    documentPrintInfoPtr->pageFormat);
                    
        if (status == noErr)
        {
            pageNumber = firstPage;
            while ((pageNumber <= lastPage) && (status == noErr)   // 8
                  && (PMSessionError(documentPrintInfoPtr->printSession) == noErr))
            {
                status = PMSessionBeginPage(                       // 9
                            documentPrintInfoPtr->printSession, 
                            documentPrintInfoPtr->pageFormat, 
                            NULL);
                            
                if (status == noErr)                               // 10
                {
                    GetPort(&currentPort);                         // 11
                                
                    status = PMSessionGetGraphicsContext(          // 12
                                documentPrintInfoPtr->printSession,
                                kPMGraphicsContextQuickdraw, (void**) 
                                &printingPort);
                                
                    if (status == noErr)
                    {
                        SetPort(printingPort);                     // 13
                                                     
  
                        if (documentPrintInfoPtr->drawDocPageProc) // 14
                            status = (*(documentPrintInfoPtr->drawDocPageProc))
                                        (documentPrintInfoPtr, pageNumber);
                                                    
                        SetPort(currentPort);                      // 15
                    }
                    tempErr =                                      // 16
                        PMSessionEndPage(documentPrintInfoPtr->printSession);
                    if (status == noErr)
                            status = tempErr;
  
                    pageNumber++;                                  // 17
                }
            }
            tempErr =                                              // 18
              PMSessionEndDocument(documentPrintInfoPtr->printSession);
            if (status == noErr)
                status = tempErr;
        }
    }
    tempErr = PMSessionError(documentPrintInfoPtr->printSession);  // 19
    if (status == noErr)
        status = tempErr;
        
    if (status != noErr)
        MTPPostPrintingError(status);                              // 20
    
    if (documentPrintInfoPtr->printSettings != kPMNoPrintSettings) // 21
    {
        PMRelease(documentPrintInfoPtr->printSettings);
        documentPrintInfoPtr->printSettings = kPMNoPrintSettings;
    }
            
    if (documentPrintInfoPtr->printSession != NULL)                // 22
    {
        PMRelease(documentPrintInfoPtr->printSession);
        documentPrintInfoPtr->printSession = NULL;
    }
}

The MTPDoPrintLoop function assumes it has been passed a valid pointer to a properly initialized print information structure for the document to print. Here’s how the function works:

  1. It calls the function MTPPagesInDoc so the Moon Travel Planner can specify the maximum number of pages to print.

  2. It calls the Carbon Printing Manager (CPM) function PMGetFirstPage to obtain the number of the first page to be printed.

    Warning

    You must use 32-bit unsigned containers to obtain the first page and last page values because in some cases the PMGetFirstPage and PMGetLastPage functions may return very large values from the print settings data structure. You should not use the constant kPrintAllPages in your print loop. That constant is used only with the PMSetLastPage and PMSetPageRange functions to specify a last page. It is not returned by the PMGetLastPage function and your code should not look for it here.

  3. It calls the CPM function PMGetLastPage to obtain the number of the last page to be printed.

  4. If the user specified a last page greater than the number of pages in the document, MTPDoPrintLoop sets the last page to the real last page in the document.

  5. It calls the CPM function PMSetFirstPage to set the first page of the page range in the print settings object for this print job.

  6. It calls the CPM function PMSetLastPage to set the last page of the page range in the print settings object for this print job. Setting the first and last page provides information to the progress dialog that is shown during printing.

  7. It calls the CPM function PMSessionBeginDocument to establish a new print job. Note that if no error results from this call, the ensuing code will always call PMSessionEndDocument to end the print job.

  8. It sets up a while loop to loop over the range of pages selected for printing. Note that the loop will terminate if any function returns an error (that is, if the variable status has a value other than noErr) or if the CPM function PMSessionError returns an error.

  9. It calls the CPM function PMSessionBeginPage to inform the printing system that the drawing that follows is part of a new page.

  10. It checks the return status after calling PMSessionBeginPage. Note that in the case that no error occurs, the ensuing code will always call PMSessionEndPage to finish printing the current page.

  11. It calls the QuickDraw function GetPort to save the current graphics port.

  12. It calls the CPM function PMSessionGetGraphicsContext to obtain the QuickDraw graphics port for the page being printed.

  13. It calls the QuickDraw function SetPort to set the graphics port to the port obtained in the previous step. You must do this before calling the document’s function to draw one page.

  14. If the print information pointer has a valid drawDocPageProc field, MTPDoPrintLoop calls that function to draw the current page.

  15. It calls the SetPort function again to set the current port back to the saved port after drawing one page.

  16. It calls the CPM function PMSessionEndPage to finish printing the current page. It uses a temporary variable to get the status for this function; then, if an error occurs, and there was no previous error, it sets the status variable to that error value. This approach ensures that the current page is always finished and that if any error occurs the loop terminates.

  17. It increments the page count within the page-printing loop.

  18. On completion of the page-printing loop, MTPDoPrintLoop calls the CPM function PMSessionEndDocument to complete the print job.

  19. It calls the CPM function PMSessionError to determine if any printing error has occurred. It again uses a temporary variable to get the status for this function to ensure that the print job is always completed and that if any error occurs, it is reported to the user.

  20. If the previous step detects a printing error, MTPDoPrintLoop calls the MTPPostPrintingErrors function to display the error to the user.

  21. Regardless of whether any error has occurred, it releases the print information structure’s print settings object, if any, and sets the field for this object to a value indicating it is no longer valid.

  22. Regardless of whether any error has occurred, it releases the print information structure’s printing session object, if any, and sets the field for this object to a value indicating it is no longer valid.

Add a Print Format String to the Localized Strings

In Section 9.2.1 you defined the constant KMTPPrintFormatStrKey to obtain a localized format string for use in displaying error strings. You saw how that constant was used in the MTPPostPrintingError function. In this section you’ll add the format string to Moon Travel Planner’s Localizable.strings file, which you learned about in Chapter 8.

To add a format string to the Localizable.strings file, you perform these steps:

  1. Open the Resources folder in the Moon Travel Planner project.

  2. Click on the Localizable.strings file.

  3. After the last current key/value entry and before the closing right bracket (}), type a semicolon (;).

  4. Insert the following line after the semicolon; the characters %ld are C formatting instructions for a long decimal value to display the error number:

    "Error format" = "Printing error: %ld"

Add Printing Code to the Main Function

To set up the Moon Travel Planner to print the text from the moon facts window, you add code to the main function in several places. First, add the following variable declaration at the top of the function with the other variables:

PMSheetDoneUPP    pageSetupDoneUPP, printDialogDoneUPP;

The PMSheetDoneUPP data type is defined by the Carbon Printing Manager (CPM) as a pointer to a sheet done function. The CPM calls your sheet done function when the user dismisses a printing dialog that is being shown as a sheet (that is, attached to the window of the document being printed).

Next you’ll use these function pointer variables to set up printing information for the moon facts window. Add the code shown in Example 9.11 to the main function after the code to install the various window event handlers.

Example 9-11. Code to Initialize a Print Information Structure for a Window

pageSetupDoneUPP = NewPMSheetDoneUPP(&MTPPageSetupDoneProc);     // 1
    if (pageSetupDoneUPP == NULL)
        goto CantSetUpPrinting;
    printDialogDoneUPP = NewPMSheetDoneUPP (&MTPPrintDialogDoneProc); // 2
    if (printDialogDoneUPP == NULL)
        goto CantSetUpPrinting;
    
    err = MTPCreatePrintInfoForWindow(gMoonFactsWindow,              // 3
                (MTPDrawDocPageProc) MTPDrawMoonFactsPage,
                pageSetupDoneUPP, printDialogDoneUPP);
    require_noerr (err, CantSetUpPrinting );

Here’s what the code in Example 9.11 does:

  1. It calls the Carbon Printing Manager function NewPMSheetDoneUPP to create a universal procedure pointer (a type of function pointer) to the MTPPageSetupDoneProc function, which is described in Section 9.2.4.3. If the call is unsuccessful, the code branches to a failure exit label, CantSetUpPrinting.

  2. It calls NewPMSheetDoneUPP again to create a universal procedure pointer to the MTPPrintDialogDoneProc function, which is described in Section 9.2.4.5. If the call is unsuccessful, the code branches to a failure exit label, CantSetUpPrinting.

    Note

    The Moon Travel Application creates these universal procedure pointers for printing and keeps them throughout the life of the application. In many cases, however, an application creates a universal procedure pointer, uses it, then disposes of it. To dispose of a universal procedure pointer of type PMSheetDoneUPP, you call the Carbon Printing Manager function DisposePMSheetDoneUPP.

  3. It calls the MTPCreatePrintInfoForWindow function to create a print information structure and attach a pointer to it as a property of the moon facts window. It passes the following values:

    • gMoonFactsWindow. A pointer to the moon facts window

    • (MTPDrawDocPageProc) MTPDrawMoonFactsPage. A pointer to the function to draw one page of the moon facts window

    • pageSetupDoneUPP. A pointer to the function to call when the user dismisses the Page Setup dialog

    • printDialogDoneUPP. A pointer to the function to call when the user dismisses the Print dialog

    If the MTPCreatePrintInfoForWindow function returns an error, the code branches to a failure exit label, CantSetUpPrinting. The macro require_noerr is described in Chapter 3. You use it to check for “show stopping” errors and jump to a label to exit the application.

Finally, you’ll add a failure label to branch to if there is an error while initializing printing. Copy the following line below CantGetNibRef:

CantSetUpPrinting:

Adjust Code in the Moon FactsWindow Event Handler

In Chapter 8 you added code to the MTPMoonFactsWindowEventHandler function to handle the Page Setup and Print commands, but that code was commented out because you hadn’t written the functions yet. Now you can remove the comment characters so that the code looks like this:

case kMTPPrintCommand:
    MTPDoPrint (gMoonFactsWindow);
    result = noErr;
    break;
case kMTPPageSetupCommand:
    MTPDoPageSetup (gMoonFactsWindow);
    result = noErr;
    break;

Test the Page Setup and Print Commands

To test the Page Setup command from the moon facts window, you perform the following steps. These steps assume you have a printer available and have already selected a default printer. If you haven’t selected a default printer, Mac OS X will prompt you to do so.

  1. Click the Build button in the upper-left corner of the Moon Travel Planner project window.

  2. Click the Run button in the upper-left corner of the project window.

  3. Choose Facts for the Traveler in the Moon menu or press Command-F.

  4. To open the Page Setup dialog, choose Page Setup in the File menu or press Command-Shift-P. The resulting Page Setup dialog is shown in Figure 9.1.

  5. Change any setting in the Page Setup dialog and close the dialog by clicking the OK button. For example, you might click one of the icons for landscape paper orientation.

  6. Open the Page Setup dialog as before. You should see that any changes you made are still present.

  7. To open the Print dialog, choose Print in the File menu or press Command-P. The resulting Print dialog is shown in Figure 9.2.

  8. Change any setting in the Print dialog. For example, you might change the printer or change the number of copies from 1 to 2.

  9. Click either the Preview button to get a preview of the printed document, or the Print button to send it to the printer. Any changes you made in the Page Setup or Print dialogs should be reflected in the resulting printed or previewed document.

  10. If you repeat the previous steps to open the Page Setup dialog, it should still reflect the changes you made. The Print dialog, however, should still reflect the original (default) settings.

Recap

In this chapter, you learned about the Carbon Printing Manager, which allows your Carbon application to take advantage of printing features available in Mac OS X, while still supporting printing in earlier versions of the Mac OS. You took a look at printing sessions (to perform one printing task), print loops (to print a range of pages), and print function sequence and scope (which determine the order in which you must call certain printing functions).

You saw that the Carbon Printing Manager provides opaque data types for key objects—the printing session, page format, and print settings objects—as well as functions for creating, modifying, extending, and saving these objects.

Finally, you added printing code to the Moon Travel Planner application to print the Facts for the Traveler window. Printing code can be a little daunting, but the code in this chapter should provide a good template for leveraging the support provided by the Carbon Printing Manager.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.46.78