开发者

Printing Off-screen PDFViews

开发者 https://www.devze.com 2022-12-16 19:57 出处:网络
I have a situation where I want to print a multi-page PDF. While I could use the PDFKit utility classes and/or quartz functions to get the information to manually write drawing/pagination code for a N

I have a situation where I want to print a multi-page PDF. While I could use the PDFKit utility classes and/or quartz functions to get the information to manually write drawing/pagination code for a NSView subclass, I had thought that quicker alternative would be to create an off-screen PDFView and tell it to print itself. When I tried this solution, the print dialog didn't go away, all of the print settings controls on the right half of the print dialog disappeared, and the application froze.

I then wrote a tiny test application with the following method that illustrates the problem. When the test program is compiled without the USE_PDF_VIEW preprocessor macro defined, the blank view displays fine. If USE_PDF_VIEW is defined, the document doesn't print, most of the print dialog controls disappear, and the app freezes. While I have other ways of accomplishing my goal, I'm curious as to why this shortcut doesn't work. Is there something a开发者_如何转开发bout Cocoa drawing I still don't understand? Am I banging into Apple Voodoo Magic(tm) behind the scenes that makes PDFView behave in a completely different way than other NSViews?

- (void)printMyStuff:(id)sender {

NSPrintInfo *currInfo = [NSPrintInfo sharedPrintInfo];

#ifdef USE_PDF_VIEW


    PDFView *pdfView = [[PDFView alloc] init];
    PDFDocument *pdfDoc = [[PDFDocument alloc] initWithURL:[NSURL fileURLWithPath:@"/Users/wls/Documents/my_document.pdf"]];
    [pdfView setDocument: pdfDoc];
    [pdfView printWithInfo:currInfo autoRotate:YES];


#else

    NSView *myView = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 500, 500)];
    NSPrintOperation *myop = [NSPrintOperation printOperationWithView:myView printInfo:currInfo];
    [myop runOperation];


#endif

}


Had the exact same problem. The PDFView needs to be added to a NSWindow in order for printWithInfo:autoRotate: to work (atleast in my case), otherwise the printing controls go blank or won't work.

Here's the complete code:

    PDFView *vDoc = [[PDFView alloc] init];
    [vDoc setDocument:pdfDoc];
    [vDoc setAutoScales: YES];
    [vDoc setDisplaysPageBreaks: NO];
    NSWindow *wnd = [[NSWindow alloc] init];
    [wnd setContentSize:vDoc.frame.size];
    [wnd setContentView:vDoc];
    [vDoc printWithInfo:printInfo autoRotate:YES];
    [wnd release];
    [vDoc release];


Building on alex-i's excellent answer, I added the following lines so the print dialog showed up in a user-friendly location:

NSRect windowRect = self.window.frame;
NSPoint printTopLeftPoint = NSMakePoint(CGRectGetMidX(windowRect), CGRectGetMaxY(windowRect));
[wnd setFrameTopLeftPoint:printTopLeftPoint];

My self.window is for my current window controller, not the temporary window.


I like alex-i's answer because it does not use private APIs. But in my case, I already have a window (and I suppose in most cases you would!), so I figured I would use that window instead of creating one. Here is what I ended up doing, using swift:

func print(_ pdfDocument: PDFDocument, using window: NSWindow) {

    // create a hidden pdf view with the document
    let pdfView = PDFView()
    pdfView.document = pdfDocument
    pdfView.autoScales = true
    pdfView.displaysPageBreaks = false
    pdfView.frame = NSMakeRect(0.0, 0.0, 50.0, 50.0)
    pdfView.isHidden = true

    // add the view to the window and print
    window.contentView.addSubview(pdfView)
    pdfView.print(nil)
    pdfView.removeFromSuperview()

}


PDFView is a subclass of NSView. The designated initializer for NSView is -initWithFrame: ... if you don't use -initWithFrame: strange things can happen. Since PDFView has no other designated initializers, -initWithFrame: is it. I'm guessing that's at least part of your problem.

Another part may be memory related. Are you using garbage collection or not? If you are, you're not keeping a reference to your PDFView anywhere, so may be getting deallocated. If you aren't using garbage collection, you're leaking your PDFView (also because you keep no reference to it, so you can release it when you're done). Same with your myView NSView instance ... you're leaking it if you're not using GC.

0

精彩评论

暂无评论...
验证码 换一张
取 消