丰富的、类似窗口的上下文菜单(如 Interface Builder)

Posted

技术标签:

【中文标题】丰富的、类似窗口的上下文菜单(如 Interface Builder)【英文标题】:Rich, Window-like Context Menu (like Interface Builder) 【发布时间】:2017-08-18 06:57:55 【问题描述】:

我需要一个上下文菜单,它的功能类似于 Interface Builder 在右键(控制)单击视图、视图控制器等时呈现的功能:

乍一看,它看起来像一个NSPanel,其样式属性设置为“HUD 面板”,包含某种大纲视图。

窗口本身应该不难实现,但是在右键(控制)单击时呈现上下文菜单的常用方法是重写方法:

func menu(for event: NSEvent) -> NSMenu?

...以NSMenu 作为返回值;不能通过 NSWindow / NSPanel 代替。


也许我可以这样做:

override func menu(for event: NSEvent) -> NSMenu? 

    // Create our popup window (HUD Panel) and present it
    // at the location of event:

    // (...actual code omitted...)

    // Prevent any actual menu from being displayed: 
    return nil 

...但感觉就像 hack;我通过假装关心呈现一个实际的NSMenu(即覆盖一个方法)来欺骗系统放弃右(控制)单击事件的时间明确地打算这样做),但利用这个时机来做不同的事情

当用户点击其他地方时,我还需要放置一些逻辑来关闭窗口(上下文菜单内置了此功能)。

我认为子类化NSMenuNSMenuItem 以获得上述行为和外观也不可行......

有更好的方法吗? 有人知道(或能够猜到)Interface Builder 的实际作用吗?


编辑: 正如@Willeke 在评论中指出的那样,面板显示的条件与上下文菜单并不完全相同,因此它肯定不是一个。这意味着为了显示窗口而劫持上述方法不仅不优雅,而且是错误的。问题涉及如何显示窗口(即检测静态、非拖动右键单击)。

【问题讨论】:

如果它看起来像一个窗口并且表现得像一个窗口,那么它很可能是一个窗口。它出现在右键单击和控制单击上。与上下文菜单不同,它不会在右拖动或控制拖动时立即出现。它与菜单没有任何关系。 @Willeke 谢谢;我也有同样的怀疑。问题仍然在于如何触发窗口的外观。根据您指出的关于右键拖动的差异,它看起来越来越像劫持menu(for:) 是错误的方法...... 【参考方案1】:

您需要从视图子类中覆盖rightMouseDown(with:) 并使用它来触发显示面板。 NSView's implementation of that method 是调用 menu(for:) 并显示返回的菜单,因此您的自定义子类可以使用它来显示其自定义菜单面板,而不是调用 super。

为了与标准上下文菜单和 Interface Builder 中的菜单完全一致,您还需要通过覆盖 mouseDown(with:) 来处理 ctrl-left-clicks 并检查事件的 modifierFlags 是否包含 .control

【讨论】:

以上是关于丰富的、类似窗口的上下文菜单(如 Interface Builder)的主要内容,如果未能解决你的问题,请参考以下文章

弹出窗口和上下文菜单

在窗口范围内限制/移动上下文菜单(右键单击)

禁用主窗口的标题上下文菜单

如何打开任何窗口的上下文菜单?

上下文菜单绑定到父窗口的 Datacontext

上下文菜单绑定到父窗口的 Datacontext