Holes in NSView or NSWindow

前端 未结 1 1793
挽巷
挽巷 2020-12-09 05:18

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

相关标签:
1条回答
  • 2020-12-09 05:36

    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.

    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
    
    0 讨论(0)
提交回复
热议问题