根据点击位置丢弃NSWindow上的鼠标事件

时间:2014-03-13 21:02:36

标签: cocoa calayer nswindow nsevent

假设我有一个浮动的,无边框的圆形NSWindow

它是圆形的,因为内容视图只是绘制一个红色圆圈。

该内容视图需要进行图层备份([contentView setWantsLayer:YES]),因为我正在对其应用 CoreAnimations ,例如动画缩放。

通常,NSWindow的可点击区域由内容视图的像素的透明度定义。但是,一旦NSWindow的内容视图成为图层支持,不幸的是,透明区域也会收到点击。

在我的情况下,这是一个严重的问题,因为我只想在半径范围内获得点击。但现在,在窗口的矩形内点击,但超出圆半径,将激活窗口(因此,整个应用程序),它不应该。窗口也可以通过其内容视图的一角进行拖动。

click location

我最初的想法是在子类中实现[NSWindow sendEvent:]并使用[theEvent locationInWindow]检查点击是否在半径范围内执行。我想我可以简单地丢弃这个事件,如果它超出了半径,那么就不要再调用[super sendEvent:theEvent]。然而,这没有用:我注意到,mouseDown:;在sendEvent之前调用window方法:方法

我搜索了很多,但我发现的唯一想法是在窗口顶部有一个像非层支持的NSWindow这样的代理,它有条件地委托点击,但这导致了不可预测的UI行为。

你们有任何想法,如何解决它?

2 个答案:

答案 0 :(得分:1)

几周后,我得出以下结果:

A)代理窗口: 使用非层支持的代理窗口,该窗口作为子窗口放置在目标窗口的顶部。代理窗口具有与目标窗口相同的形状,并且由于它不是图层支持的,因此它将正确地接收和忽略事件。代理窗口通过覆盖sendEvent:将所有事件委托给目标窗口。目标窗口设置为忽略所有鼠标事件。

B)全球鼠标指针观察: 使用NSMouseMovedMask|NSLeftMouseDraggedMaskaddGlobalMonitorForEventsMatchingMaskaddLocalMonitorForEventsMatchingMask个事件安装全局和本地事件监视器。事件监视器根据当前全局鼠标位置禁用并启用忽略所有已注册目标窗口上的鼠标事件。在圆形窗口的情况下,必须计算鼠标指针和每个目标窗口之间的距离。

这两种方法在一般情况下运作良好,但我一直在经历一些不可预测的儿童窗口方法的不当行为(儿童窗口与其父母的不同步)。的位置)。

更新:这两种方法都有一些明显的缺点: 在A)中,代理窗口有时可能不同步,可能稍微偏离实际窗口。

在B)中,即使应用程序不是最前面的应用程序,事件监视器也会在移动鼠标时对电池寿命产生很大影响。

答案 1 :(得分:1)

如果您想根据位置放弃mouseDown事件,可以使用:

CGPathContainsPoint(path,transform,point,eoFill):Bool

设置路径以匹配您的图形。圆形,椭圆形,矩形,三角形或路径甚至组合路径(带有孔的路径)。