NSPrintPanel 中默认打印预览的不同页面方向

问题描述 投票:0回答:1

我想打印一个由多个不同方向的页面组成的文档。假设每个奇数页都是纵向的,每个偶数页都是横向的。下面是我的

PrintView
类的代码:

// PrintView.h
@interface PrintView : NSView
{
    NSPrintInfo* printInfo;
    int nPages;
}
- (id)initWithParams:(CGRect)frame pages:(int)pagesCount;
- (void)setPrintInfo:(NSPrintInfo *)pi;
@end
// PrintView.m
#import "PrintView.h"

@implementation PrintView
- (id)initWithParams:(CGRect)frame pages:(int)pagesCount
{
    self = [super initWithFrame:frame];
    if (self)
    {
        nPages = pagesCount;
    }
    return self;
}

- (void)setPrintInfo:(NSPrintInfo *)pi
{
    if (printInfo != pi)
    {
        printInfo = pi;
    }
}

// print support

- (BOOL)knowsPageRange:(NSRangePointer)range
{
    range->location = 1;
    range->length   = nPages;

    return YES;
}

- (NSRect)rectForPage:(NSInteger)page
{
    if (page % 2)
        [printInfo setOrientation:NSPaperOrientationPortrait];
    else
        [printInfo setOrientation:NSPaperOrientationLandscape];

    NSRect r = NSMakeRect(0, 0, printInfo.paperSize.width, printInfo.paperSize.height);
    [self setFrame:r];
    return r;
}
@end

此代码仅生成没有任何绘图的空白页面。页面方向应用于

rectForPage:

当我在内置预览中运行打印操作(更多详细信息请参阅下面的 MRE 中的

onBtnClick
功能)时,我看到所有页面都以纵向显示:

实际上第二页应该是横向的。此外,如果我将其打印为 PDF,我可以看到 PDF 中所有页面方向都是正确的:

所以我认为问题出在内置的 Cocoa 预览中。如果最后一页为横向,则预览中的所有页面也将以横向显示。似乎只有最后一页方向适用于预览。

是否有任何解决方法可以在默认的 Cocoa 打印预览中显示不同方向的页面?还是我做错了什么?


最小可重现示例

下面是简单应用程序的代码,只需一个标有“打印”的按钮。按下该按钮开始打印过程。您可以在 Xcode 中运行并编译它(我使用 Xcode 版本 15.2)。上面列出了文件

PrintView.m
PrintView.h
,所以这里是其余的:

// main.m
#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"

int main(int argc, const char *argv[])
{
    @autoreleasepool
    {
        AppDelegate *delegate = [[AppDelegate alloc] init];
        NSApplication *app = [NSApplication sharedApplication];
        app.delegate = delegate;

        [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
        [NSApp activateIgnoringOtherApps:YES];

        NSApplicationMain(argc, argv);
    }
    return 0;
}
// AppDelegate.h
#import <Cocoa/Cocoa.h>
#import "ViewController.h"

@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (nonatomic, strong) NSWindow* window;
@property (nonatomic, strong) NSViewController* controller;
@end
// AppDelegate.m
#import "AppDelegate.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    int mask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable;
    _window = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 200, 200) styleMask:mask backing:2 defer:NO];
    _controller = [[ViewController alloc] init];

    [_window.contentView addSubview:_controller.view];

    [_window makeKeyAndOrderFront:nil];
}

- (BOOL) applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
    return YES;
}
@end
// ViewController.h
#import <Cocoa/Cocoa.h>

@interface ViewController : NSViewController
@property (nonatomic, strong) NSButton* button;
-(void) onBtnClick;
@end
// ViewController.m
#import "ViewController.h"
#import "PrintView.h"

@implementation ViewController

- (void)loadView
{
    self.view = [[NSView alloc] initWithFrame:NSMakeRect(0, 0, 200, 200)];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    _button = [NSButton buttonWithTitle:@"Print" target:self action:@selector(onBtnClick)];
    [_button setFrame:NSMakeRect(50, 50, 100, 100)];

    [self.view addSubview:_button];
}

- (void)onBtnClick
{
    int nPages = 3;     // here you can change the number of page being printed

    NSLog(@"printint %d pages...", nPages);

    PrintView* pView = [[PrintView alloc] initWithParams:NSMakeRect(0, 0, 100, 100) pages:nPages];

    NSPrintInfo* printInfo = [NSPrintInfo sharedPrintInfo];

    NSPrintPanelOptions options = NSPrintPanelShowsCopies;
    options |= NSPrintPanelShowsPageRange;
    options |= NSPrintPanelShowsPaperSize;
    options |= NSPrintPanelShowsPrintSelection;
    options |= NSPrintPanelShowsPreview;

    NSPrintOperation* pro;
    if (printInfo)
        pro = [NSPrintOperation printOperationWithView:pView printInfo:printInfo];
    else
        pro = [NSPrintOperation printOperationWithView:pView];

    [pView setPrintInfo:[pro printInfo]];

    [pro setShowsPrintPanel:YES];
    [[pro printPanel] setOptions:options];
    [pro runOperation];
}

@end
objective-c xcode macos nsprintoperation nsprintpanel
1个回答
0
投票

经过一些研究后,我发现实际上没有办法仅将横向方向应用于某些页面,而在默认打印预览中将其他页面保留为纵向。可以将横向或纵向应用于所有页面。


所以我通过旋转页面内的内容解决了我的问题。例如,这就是 Preview.app 的工作方式。

您可以使用

printInfo.jobDisposition
区分打印预览和打印到文件,打印到屏幕或实际打印机时为
NSPrintSpoolJob
,保存为 PDF 时为
NSPrintSaveJob
。这样您就可以在打印为 PDF 时保存实际的页面方向。

这里修改了

rectForPage:
功能:

- (NSRect)rectForPage:(NSInteger)page
{
    currentPage = (int)page - 1;

    if (printInfo.jobDisposition == NSPrintSaveJob)
    {
        // apply my page orientation only when saving to file
        [printInfo setOrientation:[self getCurrentPageOrientation]];
    }

    NSRect r = NSMakeRect(0, 0, printInfo.paperSize.width, printInfo.paperSize.height);
    [self setFrame:r];
    return r;
}

函数

getCurrentPageOrientation
像以前一样简单地为奇数页返回 0,为偶数页返回 1。

这里是重写的

drawRect:
函数:

- (void)drawRect:(NSRect)dirtyRect
{
    CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] CGContext];

    if (printInfo.jobDisposition == NSPrintSpoolJob && (int)printInfo.orientation != [self getCurrentPageOrientation])
    {
        // rotate content only when drawing on preview AND current page is in wrong orientation
        CGAffineTransform transform = CGAffineTransformMake(0, -1, 1, 0, 0, dirtyRect.size.height);
        CGContextConcatCTM(context, transform);
    }

    // rect sizes
    int rectW = 200;
    int rectH = 100;
    // bottom left rectangle
    CGRect rect1 = NSMakeRect(0, 0, rectW, rectH);
    CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
    CGContextFillRect(context, rect1);
}

我在每页的左下角绘制一个 100 x 200 的红色矩形。


这里是打印预览现在的屏幕截图:

自从我将

NSPrintPanelShowsOrientation
添加到
NSPrintPanelOptions
后,您甚至可以看到它在横向方向上的外观:

如果我将其打印为 PDF,我会得到指定方向的所有页面:


Apple 没有在默认打印预览中添加旋转某些页面的功能,这确实很奇怪且不直观。希望他们有一天会添加它。我也希望这个答案可以帮助那些面临类似问题的人。

© www.soinside.com 2019 - 2024. All rights reserved.