4

假设我有一个浮动的、无边界的圆形NSWindow.

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

该内容视图需要有图层支持 ( [contentView setWantsLayer:YES]),因为我在其上应用了CoreAnimations,例如动画缩放。

通常,NSWindow 的可点击区域由内容视图的像素透明度定义。然而,不幸的是,一旦 NSWindow 的内容视图变为 layer-backed,透明区域也会收到点击。

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

点击位置

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

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

各位大佬有什么思路,怎么解决?

4

2 回答 2

2

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

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

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

于 2016-01-31T13:05:40.387 回答
1

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

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

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

这两种方法通常都能很好地工作,但我一直在经历子窗口方法的一些不可预测的不当行为(其中子窗口与其父窗口的位置“不同步”)。

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

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

于 2014-03-25T14:36:36.160 回答