Cocoa 如何使透明的NSView子类处理鼠标事件? 问题

Cocoa 如何使透明的NSView子类处理鼠标事件? 问题,cocoa,Cocoa,我在透明的NSWindow上有一个透明的NSView。视图的drawRect:方法在视图上绘制一些内容(NSImages、NSBezierPaths和NSStrings),但部分内容保持透明 单击已绘制的视图区域将调用常用的鼠标事件处理方法(mouseDown:和mouseUp:) 单击透明区域可以聚焦在我的透明窗口后面的任何窗口 我希望使透明区域的部分可单击,以便在视图上绘制的元素之间意外单击不会导致窗口失去焦点 已尝试的解决方案 重写NSView的hitTest:方法。发现只有在单击视图

我在透明的
NSWindow
上有一个透明的
NSView
。视图的
drawRect:
方法在视图上绘制一些内容(
NSImage
s、
NSBezierPath
s和
NSString
s),但部分内容保持透明

单击已绘制的视图区域将调用常用的鼠标事件处理方法(
mouseDown:
mouseUp:

单击透明区域可以聚焦在我的透明窗口后面的任何窗口

我希望使透明区域的部分可单击,以便在视图上绘制的元素之间意外单击不会导致窗口失去焦点


已尝试的解决方案
  • 重写
    NSView
    hitTest:
    方法。发现只有在单击视图的非透明区域时才调用了
    hitTest:
  • 覆盖
    NSView
    opaque祖先
    方法。发现在单击视图的任何部分时未调用此函数
  • drawRect:
    方法中,用
    [NSColor clearColor]
    填充部分透明区域,并使用几乎但不完全透明的颜色。这没有效果
  • 使用
    NSTrackingArea
    类进行实验。这似乎只增加了对
    mouseEntered:
    mouseExited:
    mouseMoved:
    cursorUpdate:
    方法的支持,而不是
    mouseUp:
    mouseDown:
您是否尝试覆盖

- (NSView *)hitTest:(NSPoint)aPoint 

在NSView SubCass?

中,您可以覆盖
NSView
中的
hitTest
方法,使其始终返回自身

根据,如果点不在
NSView
内,则
hitTest
方法将返回用户单击的NSView,或者
nil
。在本例中,我将调用
[super-hitTest:
,然后仅当结果为
nil
(以防自定义视图包含子视图)时才返回当前视图


据我所知,windows的透明部分的单击事件根本不会传递到应用程序,因此任何正常的事件链覆盖(即-hitTest:,-sendEvent:,等等)都无法工作。我能想到的唯一方法就是使用石英事件点击捕捉所有鼠标点击,然后手动确定它们是否位于窗口的透明区域上。坦白地说,这听起来像是一个巨大的皮塔,收获不大。

乔治:你提到你试着用几乎但不完全透明的颜色填充食物。在我的测试中,它似乎只有在alpha值高于0.05时才起作用,因此您可能会有这样的运气:

[[NSColor colorWithCalibratedRed:0.01 green:0.01 blue:0.01 alpha:0.05] set];

这是一个丑陋的难题,但它可能足够好,可以避免使用事件点击。

我也有同样的问题。看起来
[window setIgnoresMouseEvents:NO]
可以执行此操作


(至少在Lion上。请参阅)

您可以使用事件监视器捕捉窗口/视图外的事件。 您可以执行以下操作:

NSView* windowContent = [window contentView];
[windowContent setWantsLayer:YES]
确保背景是透明的:

[[windowContent layer] setBackgroundColor:[[NSColor clearColor] CGColor]];

另一个选择是添加一个透明的背景图像,填充contentView。

谢谢Tristan。我之前确实尝试过这个方法,但是我的子类的hitTest:方法在我单击非透明区域之前不会被调用。谢谢James,不幸的是,hitTest:方法在我单击NSView的不透明区域之前不会被调用。谢谢Boaz。我已经看过了活动API,我想你是对的,它太麻烦了!
[[windowContent layer] setBackgroundColor:[[NSColor clearColor] CGColor]];