【问题标题】:Holes in NSView or NSWindowNSView 或 NSWindow 中的漏洞
【发布时间】:2012-04-02 01:27:06
【问题描述】:

是否可以切掉 NSWindow 或 NSView 的一部分并让它们看穿?我有一个带有 NSView 的 NSWindow,我想要:

A) 在 NSWindow 上打一个洞以便能够看穿它或

B) 将我的 NSWindow 背景设置为具有清晰的颜色,然后在顶部制作一个 NSView 并将我的 NSViews 不透明度的某个部分设置为能够看到桌面。

这是我想要创建的效果:

【问题讨论】:

标签: objective-c xcode cocoa


【解决方案1】:

是的,这是可能的,实际上并不难。

在您的窗口子类中,您需要将窗口背景颜色设置为透明

self.backgroundColor = NSColor.clearColor;

并告诉合成引擎你的窗口部分是透明的,需要在窗口移动时重新绘制

[self setOpaque:NO];

在 macOS 的早期版本中没有必要设置背景颜色,许多答案仍然没有提及这一事实。我已经验证,至少从 macOS 10.11 开始,它是必要的。

在你的 NSView 子类中,你必须用你选择的颜色渲染新背景(否则窗口是完全透明的,只有标题栏会显示),然后用

在视图中渲染一个洞
NSRectFillUsingOperation(NSMakeRect(50, 50, 100, 100), NSCompositingOperationClear);

这会产生预期的效果,并且也适用于 Mojave 的暗模式等。

完整代码:

@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

【讨论】:

  • 如果我想保留第一个视图并添加第二个视图或子视图,我还能使用 NSCompositeClear 吗?是否可以通过视图和窗口进行查看?
  • @GrantWilkinson 如this screenshot 所示,父视图的绘制代码中的NSCompositeClear 不会通过子视图进行绘制。 NSCompositeClear 在子视图的绘制代码中,然而,将通过其父视图进行绘制。
  • 答案中缺少什么。 1.window 背景颜色应该是 0.01 alpha 值,以便获取事件。 2.自定义子视图,您可以填充颜色并在使用合成操作后清除您想要透明度的矩形
  • 我错过了MyWindow 上的hasShadow。这就是为我解决所有问题的原因。 (当时我并不关心阴影。)MyView.drawRect 似乎只是在第一次抽奖时才通过。当我在其他地方重画洞时,后备窗口似乎没有更新洞。切换解决了这个问题。谢谢!
  • 这是一个很好的答案。唯一的问题是窗口的标题栏在暗模式下行为不端。它有一个 NSVisualEffectView ,只有在它后面有窗口背景时才看起来正确。如果您在标题栏位于亮点上方时激活应用程序,它会记住并随身携带。我没有解决方案,但我认为其他人应该知道。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多