objective-cxcodemacosnsprintoperation

Printing multiple pages in Objective-C


I have a printing function like so:

- (void)sendToPrinter:(int)code {
    NSPrintInfo *printInfo;
    NSPrintInfo *sharedInfo;
    NSPrintOperation *printOp;
    NSMutableDictionary *printInfoDict;
    NSMutableDictionary *sharedDict;

    sharedInfo = [NSPrintInfo sharedPrintInfo];
    sharedDict = [sharedInfo dictionary];
    printInfoDict = [NSMutableDictionary dictionaryWithDictionary:
                     sharedDict];
    [printInfoDict setObject:NSPrintSpoolJob 
                      forKey:NSPrintJobDisposition];
    printInfo = [[NSPrintInfo alloc] initWithDictionary: printInfoDict];
    [printInfo setHorizontalPagination: NSAutoPagination];
    [printInfo setVerticalPagination: NSAutoPagination];
    [printInfo setVerticallyCentered:NO];
    [printInfo setLeftMargin:10];
    [printInfo setRightMargin:10];
    [printInfo setTopMargin:10];
    [printInfo setBottomMargin:10];
    [printInfo setScalingFactor:1.1];
    printOp = [NSPrintOperation printOperationWithView:sheet 
                                             printInfo:printInfo];
    [printOp setShowsPrintPanel:YES];
    [printOp runOperation];
}

This prints a representation of a page preview called sheet, which is an NSBox. This works fine.

Sometimes I have more information that can fit on a page and so I have 'next page' buttons that fill sheet with a representation of Page2, Page3, etc. by reloading sheet with the relevant data. This works fine.

Now, if I want to print out information that will fit on 2 or 3 pages rather than 1, I want to be able to feed NSPrintInfo or NSPrintOperation additional pages manually before it goes to print, rather than pagination. Something like:

printOp = [NSPrintOperation printOperationWithView:sheet 
                                             printInfo:printInfo];
[self nextPage];
printOp = [NSPrintOperation printOperationWithView:sheet 
                                             printInfo:printInfo];
[self nextPage];
printOp = [NSPrintOperation printOperationWithView:sheet 
                                             printInfo:printInfo];
// run this in loop until all the pages are accounted for
[printOp setShowsPrintPanel:YES];
[printOp runOperation];

Any solutions? Thanks in advance.


Solution

  • You can't avoid pagination with the Cocoa printing system; as your comment mentions, you'll need to go to something lower-level.

    However I don't think it should be too hard to adapt what you're doing to pagination. Take a look at Providing a Custom Pagination Scheme and Customizing a View's Drawing for Printing. Just subclass NSBox, provide rects that are the size of each page and adjust your coordinate system in beginPageInRect:atPlacement: so the box draws into the rect. You can get the current page number with [[NSPrintOperation currentOperation] currentPage] so you know what to draw.

    Update: Turns out you don't even need to mess with your coordinate system if your view is already the right size. Here's an example of a very simple NSBox subclass that just changes its title for every page:

    @implementation NumberBox
    
    - (BOOL)knowsPageRange:(NSRangePointer)aRange;
    {
        *aRange = NSMakeRange(1, 10);
        return YES;
    }
    
    - (void)beginPageInRect:(NSRect)aRect atPlacement:(NSPoint)location;
    {
        [self setTitle:[NSString stringWithFormat:@"Page %d", [[NSPrintOperation currentOperation] currentPage]]];
        [super beginPageInRect:aRect atPlacement:location];
    }
    
    - (NSRect)rectForPage:(NSInteger)page;
    {
        return [self bounds];
    }
    
    @end
    

    One thing that may not have been obvious is the need to invoke the superclass's implementation of beginPageInRect:atPlacement:. Also, do not draw in rectForPage:, it won't work properly—that's the role of the beginPage…/endPage methods.