Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
558 views
in Technique[技术] by (71.8m points)

objective c - Holes in NSView or NSWindow

IS it possible to cut out parts of a NSWindow or an NSView and make them see through? I have an NSWindow with an NSView and I want to either:

A) make a hole in the NSWindow to be able to see through it or

B) set my NSWindow background to have a clear color and then make an NSView on top and set a certain part of my NSViews opacity to be able to see through to the desktop.

This is the effect I am trying to create:

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Yes, it's possible, and actually not that hard.

In your window subclass, you need to set the window background color to transparent

self.backgroundColor = NSColor.clearColor;

and tell the compositing engine that parts of your window are transparent and need to be redrawn when the window moves

[self setOpaque:NO];

Setting the background color was not necessary in early versions of macOS and many answers still do not mention that fact. I've verified that at least since macOS 10.11 it is necessary.

In your NSView subclass, you must render the new background with a color of your choice (otherwise the window is entirely transparent and only the title bar will show) and then render a hole in the view with

NSRectFillUsingOperation(NSMakeRect(50, 50, 100, 100), NSCompositingOperationClear);

This gives the desired effect and also works in Mojave's dark mode etc.

window with hole in dark mode

Full code:

@interface MyWindow : NSWindow
    - (id)initWithContentRect:(NSRect)contentRect styleMask:( unsigned    int)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag;
@end

@implementation MyWindow
   - (id)initWithContentRect:(NSRect)contentRect styleMask:( unsigned   int)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag {
        self = [super initWithContentRect:contentRect styleMask : aStyle backing :bufferingType defer:flag ];
        if (self)
        {
            self.backgroundColor = NSColor.clearColor;
            [self setOpaque:NO];
            [self setHasShadow:NO];
        }
        return self;
}
@end

@interface MyView : NSView
- (void)drawRect:(NSRect)rect;
@end

@implementation MyView
- (void)drawRect:(NSRect)rect
{
    [[NSColor windowBackgroundColor] set];
    NSRectFill(self.bounds);
    NSRectFillUsingOperation(NSMakeRect(50, 50, 100, 100), NSCompositingOperationClear);
}
@end

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...