Programming Guide: Printing

# Programming Guide

## Printing

For the OS/2 and Windows platforms, to print a document, the user selects Print from the Document menu, and the root part displays a print dialog box (see "Page Setup and Print document"). If the user confirms the print command, the root part then sets up the environment for printing and prints the document. (When your part is the root part, it also handles the Page Setup command.)

In printing, the printer is represented by a canvas object that is separate from the screen display's canvas, although part editors in general use normal drawing calls to print their content.

Because any part can be the root part of a document, all parts should in general support the printing commands. The root part has greater responsibility in printing, but all visible embedded parts are asked to draw themselves, and they can adjust their drawing process for the presence of a static canvas. They can also directly access the platform-specific printing structure, if necessary.

OpenDoc does not replace a platform's printing interface; OpenDoc objects provide access to platform-specific structures and provide a context in which you make platform-specific calls.

This section first discusses the specific printing responsibilities of the root part, then addresses those of embedded parts, and finally notes aspects of printing that apply to all parts.

### Root-Part Responsibilities

If your part is the root part, it defines the basic printing behavior of its document. It sets things up, makes the platform-specific printing calls, and performs any frame negotiation that is to occur.

#### Choosing a Frame for Printing

If your part's document uses the same page layout for printing as for screen display, printing is simpler. You use your part's existing display frame (the window's root frame) as the frame for printing. That way, you need not create any new frames, including embedded frames. Using your existing display frame makes most sense in situations where you do not engage in frame negotiation, because you can reuse the same layout after printing.

For greater flexibility, you may want to allow the printed version of your document to have a somewhat different layout from the onscreen version. For example, you may want to give embedded parts a chance to remove scroll bars and resize their frames or otherwise lay themselves out differently. To do that, and to retain your original layout for post-printing display, you can create a separate display frame for printing, as described next.

#### Printing the Document

After you have followed the steps listed in "Page Setup and Print document", and after the user has confirmed the print dialog, your part is ready to print its document. It is assumed that you have created a platform-specific printing structure, such as a presentation space associated with a printer device context on OS/2. On the Windows platform, you would create a device context (DC) for the printer, a PRINTDLG structure which describes the specifics of the print job and a DOCINFO structure which describes additional details about the document to be printed. You should then take these general steps:

1. If you do not change layout or support frame negotiation for printing, skip this step and use your current display frame as the printing frame. Otherwise, create a separate printing frame, like this:

   - Call your draft's CreateFrame method to create a new, nonpersistent frame as a display frame for your part, to be used as the printing frame.

   - Also create new frames for each of your part's embedded parts, with the printing frame as their containing frame.

2. Create an external transform and clip shape for your printing facet. Make the clip shape equal to your page size.

3. Create a new facet for the printing frame, using the window state object's CreateFacet method. Assign the transform and clip to the printing facet.

4. Create a platform canvas object using the facet's CreatePlatformCanvas method, and specify the platform-specific printer context you created earlier.

5. Create a static canvas with the printing facet's CreateCanvas method. Use the SetPlatformCanvas method to assign the platform canvas object to the canvas. Use the SetPlatformPrintJob method to assign the platform-specific printing information to the canvas. On the OS/2 platform, you might create and initialize a PRINTDEST structure and use it when calling SetPlatformPrintJob. On the Windows platform, you might use a PRINTDLG structure.

6. Assign the canvas to the printing facet by calling the facet's ChangeCanvas method. Notify the printing frame of the presence of the printing facet by calling its FacetAdded method.

   (If you have not created a separate printing frame, each of your embedded parts with a facet is at this point notified of the presence of a static canvas and may attempt frame negotiation. As root part, you may permit or deny the requests).

7. Loop through all pages in your part's content area (or the page range specified in the job dialog box), and print each one. For each page, do the following:

   - Reset your printing facet's clip shape and/or transform so that it covers this page.

   - Create facets for your newly visible embedded frames, and release facets for frames no longer in view. At this point, allow frame negotiation with your part's embedded parts if you support negotiation.

   - Invalidate the printing facet's area and force a redrawing, by calling the facet's Update method.

8. When finished printing, clean up. Remove the printing facet from the printing frame and release it. Delete the platform-specific structures (such as the print job) and the platform canvas object that you have created. If you have created a printing frame, remove it by calling its Remove method.

### Embedded-Part Responsibilities

Embedded parts have these few specific responsibilities in printing.

#### Engaging in Frame Negotiation

Your part must handle printing properly when it is an embedded part and is assigned a new display frame or facet. It should examine the facet's associated canvas to determine whether it is dynamic or static and perform frame negotiation if appropriate. On a static canvas, you might engage in a frame negotiation to make all of your part's content visible, or you might need to resize your frame to account for elimination of scroll bars or other items that are appropriate for screen display only.

The best point at which to test for the presence of a static canvas is when your facet is added or when its canvas changes, not when your Draw method is called. At drawing time it is too late to engage in frame negotiation.

#### Responding to GetPrintResolution

Your part may receive a call to its GetPrintResolution method as a printing job is being set up. This is its interface:

    ODULong GetPrintResolution(in ODFrame frame);

Your GetPrintResolution method should first call the GetPrintResolution method of any of its own embedded parts that would be visible within the specified frame. It should then return the highest of all returned values and your own part's minimum printing resolution (in dots per inch) as the method result.

On the OS/2 and Windows platforms, the print resolution for a print job cannot be set programmatically; however, a part that is initiating the print job might try to query the resolution of available printers to find one that is satisfactory.

### Issues for All Parts

Your part draws to the printer canvas just as it draws to its window canvas. Your Draw method is called when the facet that displays your part is being imaged.

When your part draws to a static canvas (use the IsDynamic method of the canvas to find out), you may not want to draw adornments and interactive features such as scroll bars that are appropriate for screen display only.

On a static canvas, you may also want to perform color matching to take into account the characteristics of the device on which you are drawing.

Although all printing canvases are static, not all static canvases are for printing. The presence of a static canvas does not guarantee that a print job or job object exists. You can call the HasPlatformPrintJob method of the canvas to find out if a printing structure exists. If it does, it is available through the GetPlatformPrintJob method of the printing canvas. You might want to access the print job or job object directly to determine, for example, whether you are printing on a PostScript printer.

[ Top | Previous | Next | Contents | Index | Documentation Homepage ]