【问题标题】:How to achieve mouse click-through on NSView with CALayer?如何使用CALayer在NSView上实现鼠标点击?
【发布时间】:2011-03-21 14:51:35
【问题描述】:

我有一个圆形的自定义无边框 NSWindow。为此,我使用了一个自定义的 NSView 来绘制一个实心圆圈。

鼠标点击窗口内容矩形内的一个透明像素直接穿过窗口到达它后面的任何应用程序。我的应用程序拦截了实心圆圈内的点击。到目前为止一切顺利。

问题在于,通过以下行,上述行为发生了变化,并且窗口内容矩形内的所有点击都被拦截,透明像素与否:

[circleView setWantsLayer:YES];

有没有办法让CALayer 实例的透明像素点击通过窗口/视图/层到达它后面的应用程序?

本质上与下面描述的问题完全相同(只是该解决方案并非在所有情况下都有效,因为它不支持动画):

http://www.cocoabuilder.com/archive/cocoa/235281-clicking-through-nsview-with-calayers.html

【问题讨论】:

  • circleView是窗口的内容视图还是内容视图的子视图?

标签: cocoa core-animation mouseevent calayer nswindow


【解决方案1】:

我不完全确定这是否适用于图层支持的视图,但一种可能的解决方案是在您的圆形视图子类上覆盖 - (NSView *)hitTest:(NSPoint)aPoint 并检查 aPoint 是否位于圆圈的路径内。如果它在圈外,则从该方法返回 nil 应该会导致点击通过。

【讨论】:

  • 测试很快,不幸的是不起作用。即使 hitTest 返回 nil,点击仍会传递到窗口。
  • 正如 [1] 末尾所暗示的,它似乎可以使用条件 [NSWindow setIgnoresMouseEvents:NO] 技巧,通过使用始终监听的 NSTrackingArea,这是内容视图的一部分. [1] — cocoabuilder.com/archive/cocoa/…
【解决方案2】:

带有 CGPath 的 CAShapeLayer 可以工作,或者您可以创建一个 CAShapeLayer 作为内容层的遮罩。

【讨论】:

    【解决方案3】:

    当您在NSView 中创建CALayer 时,您可以向 Views 支持层询问其在其层层次结构中接收器的最远后代QuartzCore 中的 CALayers 也有一个 hitTest: 方法。

    一旦你在这一点上捕捉到一个层,你可以要求你的CALayer 或 CALayer 子类的给定 name 属性,以防你有多个 CALayer 并且需要知道它们中的哪一个被准确命中。
    CALayers 没有 .tag 属性。

    -(NSView *)hitTest:(NSPoint)p {
        __kindof CALayer *catched = [self.layer hitTest:point];
        NSString *className = NSStringFromClass([catched class]);
        NSLog(@"x%0.1f y%0.1f class:%@ name:%@", p.x, p.y, className, catched.name);
        return [super hitTest:p];
    }
    

    注意:如果没有找到图层,结果可能是null

    【讨论】:

    • 10 年后回答,因为 google 把我带到了这里。
    猜你喜欢
    • 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
    相关资源
    最近更新 更多