9

我有一个 NSMenu 使用 popUpStatusItemMenu 从 NSStatusItem 中弹出。这些 NSMenuItem 显示了一堆不同的链接,每个链接都通过 setAction: 连接到目标的 openLink: 方法。这种安排已经运行了很长时间。用户从菜单中选择一个链接,然后 openLink: 方法处理它。

不幸的是,我最近决定尝试使用 NSMenuItem 的 setView: 方法来提供更好/更流畅的界面。基本上,我只是停止设置标题,创建 NSMenuItem,然后使用 setView: 来显示自定义视图。这非常有效,菜单项看起来很棒,并且显示了我的自定义视图。

但是,当用户选择一个菜单项并释放鼠标时,该操作不再起作用(即,未调用 openLink:)。如果我只是简单地注释掉 setView: 调用,那么操作会再次起作用(当然,菜单项是空白的,但操作会正确执行)。那么,我的第一个问题是为什么设置视图会破坏 NSMenuItem 的操作。

没问题,我想,我会通过在我的自定义视图中检测 mouseUp 事件并从那里调用我的操作方法来修复它。我将此方法添加到我的自定义视图中:

- (void)mouseUp:(NSEvent *)theEvent {
  NSLog(@"in mouseUp");
  }

没有骰子!这个方法永远不会被调用。

不过,我可以设置跟踪矩形并接收 mouseEntered: 事件。我在 mouseEntered 例程中进行了一些测试,如下所示:

if ([[self window] ignoresMouseEvents]) {  NSLog(@"ignoring mouse events");  }
else {  NSLog(@"not ignoring mouse events");  }
if ([[self window] canBecomeKeyWindow]) {  dNSLog((@"canBecomeKeyWindow"));  }
else {  NSLog(@"not canBecomeKeyWindow");  }
if ([[self window] isKeyWindow]) {  dNSLog((@"isKeyWindow"));  }
else {  NSLog(@"not isKeyWindow");  }

并得到以下回复:

not ignoring mouse events
canBecomeKeyWindow
not isKeyWindow

这是问题吗?“不是键窗口”?大概这不好,因为 Apple 的文档说“如果用户单击不在键窗口中的视图,默认情况下,窗口会向前移动并设为键,但不会调度鼠标事件。” 但是必须有一种方法可以检测到这些事件。如何?

添加:

[[self window] makeKeyWindow];

没有效果,尽管 canBecomeKeyWindow 是 YES。

4

7 回答 7

15

将此方法添加到您的自定义 NSView 中,它将与鼠标事件一起正常工作

- (void)mouseUp:(NSEvent*) event {
    NSMenuItem* mitem = [self enclosingMenuItem];
    NSMenu* m = [mitem menu];
    [m cancelTracking];
    [m performActionForItemAtIndex: [m indexOfItem: mitem]];
}

但是我遇到了钥匙处理问题,如果你解决了这个问题,也许你可以去我的问题并帮助我一点。

于 2010-08-07T08:45:54.620 回答
10

将此添加到您的自定义视图中,您应该没问题:

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
    return YES;
}
于 2010-02-09T19:57:25.650 回答
9

我将此方法添加到我的自定义视图中,现在一切正常:

- (void)viewDidMoveToWindow {
    [[self window] becomeKeyWindow];
}

希望这可以帮助!

于 2010-03-13T05:56:57.377 回答
3

我已将此版本更新为SwiftUI Swift 5.3

final class HostingView<Content: View>: NSHostingView<Content> {
    override func viewDidMoveToWindow() {
        window?.becomeKey()
    }
}

然后像这样使用:

let item = NSMenuItem()
let contentView = ContentView()
item.view = HostingView(rootView: contentView)

let menu = NSMenu()
menu.items = [item]
于 2020-09-27T15:05:32.593 回答
2

到目前为止,实现目标的唯一方法是手动注册一个跟踪区域updateTrackingAreas- 谢天谢地,它被称为,如下所示:

override func updateTrackingAreas() {
    let trackingArea = NSTrackingArea(rect: bounds, options: [.enabledDuringMouseDrag, .mouseEnteredAndExited, .activeInActiveApp], owner: self, userInfo: nil)
    addTrackingArea(trackingArea)
}
于 2018-12-31T20:08:47.433 回答
-1

请参阅 Apple 的名为 CustomMenus 的示例代码 在其中,您会在 ImagePickerMenuItemView 类中找到一个很好的示例。

让菜单中的视图像普通的 NSMenuItem 一样工作并不简单或微不足道。有一些真正的决定和编码要做。

于 2014-02-26T03:39:31.230 回答
-1

最近我需要显示一个 NSStatusItem 的自定义视图,在单击它时显示一个常规的 NSMenu 并支持在状态图标上进行拖放操作。

我主要使用可以在这个问题中找到的三个不同来源解决了我的问题。

希望它可以帮助其他人。

于 2013-02-27T11:57:10.993 回答