【问题标题】:Is there a way to tell the width of the MainMenu?有没有办法告诉 MainMenu 的宽度?
【发布时间】:2013-04-28 09:39:42
【问题描述】:

我正在开发的应用程序需要能够否决菜单栏点击。有多种方法可以在单击菜单时收到通知(主要是NSMenu 通知和NSMenu 委托),但据我所知,它们都不会让您拒绝该操作。

我一直在考虑的解决方案是使用无边框透明窗口,并将其覆盖在菜单栏上。通过将窗口级别设置为足够高的值(在本例中为NSStatusWindowLevel),它可以有效地定位和绘制在菜单栏上方,捕获本来会转到它的鼠标事件。这样,我就有了我想要的东西。

该解决方案的问题在于它还掩盖了状态栏的事件(右对齐的全局菜单项),我不需要或不想否决这些事件。要解决这个问题,我需要能够分辨状态栏的范围或菜单栏的范围,但我发现两者都没有明显的方法。 NSApp.mainMenu.size 返回主菜单的大小,就好像它被布置在弹出菜单中一样,这显然不是我需要的。

有没有更好的方法来屏蔽菜单栏的事件,或者有什么方法可以找到它的宽度,不包括状态栏?

这可能听起来很肮脏,而且确实如此。我正在为一个旧平台的应用程序级模拟器做这件事,当用户点击菜单栏时,应用程序负责显示菜单,因此当发生这种情况时,它几乎可以做任何它想做的事情。

【问题讨论】:

    标签: macos cocoa


    【解决方案1】:

    菜单栏的宽度很简单:就是菜单栏屏幕的宽度。这包括应用程序的所有菜单:

    这是来自Layers,所以我认为你的应用不能做得更好。

    所以,你将不得不减去状态栏。

    使用 Quartz Window Services 很容易。

    首先,在the main menu window levelorder it back 上创建一个无边框、不透明、背景清晰的空窗口——即,在真正的主菜单后面

    然后,获取您窗口的窗口编号,并将其传递给the CGWindowListCreate function,指定您希望所有窗口高于另一个窗口。

    为了获得额外的稳健性(只是为了确保不包含光标或其他内容),请在相反的方向执行相同的操作:在同一窗口级别创建第二个窗口,order it front(在菜单前面和状态栏),并创建该窗口后面的窗口列表。

    两个数组中的窗口是菜单栏和所有状态项。宽度与主菜单屏幕([NSScreen screens][0])相同的是菜单栏; union所有状态项的矩形一起,将菜单栏的矩形剪切到状态项矩形的原点。

    请注意,所有这些都假设菜单栏和状态项以某种方式组织,这可能会在任何操作系统更新中发生变化。

    【讨论】:

    • 我害怕我不得不做这样可怕的事情。虽然,我也发现菜单栏在状态栏下方,可以在两者之间订购透明窗口。这在我的 TODO 列表中并不是特别高(我在问是否有一个简单的解决方案可以在几分钟内实施),但我可能会调查这两个选项。
    • @zneak:我不知道在菜单栏上方但在状态栏下方订购一个窗口是否有用,因为它下方会有很多窗口,而不仅仅是菜单栏,而且(AFAIK)不保证数组中项目的顺序。您可以自己遍历数组并整理出主菜单窗口级别下方的每个窗口,但是将窗口放在菜单栏下方并仅询问其上方的窗口会做同样的事情。
    最近更新 更多