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
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…