【问题标题】:Change cursor for full screen NSWindow更改全屏 NSWindow 的光标
【发布时间】:2011-11-15 21:16:12
【问题描述】:

我正在尝试制作一个允许在 ShieldingWindowLevel 绘制的覆盖窗口,但是当窗口出现时,光标仍然是默认指针。我想把它改成十字准线。在我感到困惑之前拥有控制器 NSCursors 为什么从未调用过 resetCursorRects

我手动创建窗口如下(在我的 AppController 类中):

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // Create the window
    NSRect frame = [[NSScreen mainScreen] frame];

    // Provide a small area on the right to move the cursor in-and-out of the window.
    frame.size.width = frame.size.width - 20; 
    self.window  = [[NSWindow alloc] initWithContentRect:frame
                                               styleMask:NSBorderlessWindowMask
                                                 backing:NSBackingStoreBuffered
                                                   defer:NO];
    [self.window setAcceptsMouseMovedEvents:YES];
    [self.window setOpaque:NO];
    [self.window setLevel:CGShieldingWindowLevel()];
    [self.window setBackgroundColor:[NSColor colorWithDeviceRed:0.0 green:0.0 blue:1.0 alpha:0.2]];

    // Create the subview
    ScreenOverlayView *subview = [[ScreenOverlayView alloc] initWithFrame:NSZeroRect];
    [[self.window contentView] addSubview:subview];

    // Add subview and show window
    [self.window setContentView:subview];
    [self.window makeFirstResponder:subview];
    [self.window orderFrontRegardless];
}

使用以下 NSView 子类:

@implementation ScreenOverlayView
- (void) resetCursorRects {
    [super resetCursorRects];
    [self addCursorRect: [self bounds]
                 cursor: [NSCursor crosshairCursor]];
} 
// ...
@end

我创建了一个示例项目来展示这个案例并将它发布到github,最有趣的文件是ScreenOverlayView.mAppDelegate.m

我应该指出,我也花了很多时间尝试使用 NSTrackingArea 来实现这一点,正如您在示例项目中看到的那样。如果鼠标在出现后进入视图,则跟踪区域有效,但如果它在内部开始,则无效。如果我有办法设置初始光标,使用 MouseEnter 和 MouseLeave 会很好,但它只会在变回之前改变一瞬间。

如何让 resetCursorRects 被调用 - 或者 - 当我将光标移动到超级视图时如何设置光标?

【问题讨论】:

    标签: objective-c macos cocoa


    【解决方案1】:

    关键是您确实需要创建NSWindow 的自定义子类,以抵消无边框窗口 (NSBorderlessWindowMask) 的一些默认行为。

    示例项目的更新版本位于 http://www.markdouma.com/developer/full-screen-overlay.zip

    在其中,我创建了一个自定义的 MDScreenOverlayWindow 类,它覆盖了 NSWindow 的 canBecomeKeyWindow 方法,如下所示:

    // Windows created with NSBorderlessWindowMask normally can't be key,
      but we want ours to be
    - (BOOL)canBecomeKeyWindow {
        return YES;
    }
    

    这将使您的视图成为关键,并且基本上所有其他内容都可以正常工作。

    另一件可能值得注意的是drawRect: 方法。 (看起来你可能来自 iOS)。您可能想查看NSBezierPath,因为它可能会简化您的一些绘图代码。例如,我相信您的绘图代码可以合并为以下内容:

    - (void)drawRect:(NSRect)rect {
        // the color should probably be "pre-multiplied" by the alpha
        // premultiplied version:
        [[NSColor colorWithCalibratedRed:0.8 green:0.0 blue:0.0 alpha:0.8] set];
        [NSBezierPath setDefaultLineWidth:2.0];
        [NSBezierPath strokeLineFromPoint:currentLocation toPoint:downLocation];
    }
    

    【讨论】:

    • 最初我使用的是 NSResizableWindowMask,我认为它会成为关键——我会试试看。
    • 另外,感谢您提供有关使用旧绘图 API 的提示,它是否更简洁(当您更喜欢 obj-c 而不是普通 c 时,这很好)
    • 3 天把我的头撞在桌子上。我欠你一杯啤酒。或者 12. 谢谢你——工作得很好。
    • 我正在改变我的宗教信仰!感谢 NSGod 的签收!
    猜你喜欢
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    相关资源
    最近更新 更多