Swift:10.10 中的 NSStatusItem 菜单行为(例如,仅在鼠标右键单击时显示) [英] Swift: NSStatusItem menu behaviour in 10.10 (e.g. show only on right mouse click)

查看:108
本文介绍了Swift:10.10 中的 NSStatusItem 菜单行为(例如,仅在鼠标右键单击时显示)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 Swift 中编写一个简单的状态栏应用程序,并尝试使用 OS X 10.10 中引入的新 NSStatusItem API.

I am writing a simple status bar app in Swift, and attempting to use the new NSStatusItem API introduced in OS X 10.10.

我的目标界面是在 statusItem 上单击鼠标左键以打开和关闭核心功能,并使用鼠标右键单击(或控制单击)选项显示设置菜单.对于此功能,我不需要自定义视图或弹出框.

The interface I'm aiming for is a simple left mouse click on the statusItem to toggle a core feature on and off, with a right mouse click (or control-click) option to show a settings menu. I have no need for a custom view or popover for this functionality.

默认情况下,如果将 NSMenu 分配给 NSStatusItem,它将在左键和右键单击时显示菜单.我想将行为更改为仅在右键单击时显示菜单,或者作为一种解决方法,防止在左键单击时弹出菜单

By default, if a NSMenu is assigned to a NSStatusItem, it will display the menu on both a left and right click. I want to change the behaviour to only show the menu on a right click, or as a workaround, prevent the menu popping up on a left click

以前,似乎要控制 NSStatusItem 上的鼠标事件,必须使用覆盖的鼠标事件设置自定义视图(请参阅 这个相关问题).

Previously, it seems that to get control of mouse events on a NSStatusItem, one had to set a custom view with overridden mouse events (see this related question).

在新的 NSStatusItem API 在 10.10 中引入,设置自定义视图的方法已被弃用,并且看起来不鼓励这种行为.根据@Taylor 在 this answer 中的说法,应该通过 statusItemObject.button() 但截至撰写本文时,还没有 NSStatusBarButton 的文档,并且返回的对象是只读的,不能用具有覆盖鼠标事件处理程序的自定义按钮替换.

In the new NSStatusItem API introduced in 10.10, methods for setting a custom view have been deprecated, and it looks like this behaviour is discouraged. According to @Taylor in this answer a few of the deprecated behaviours should be used through the NSStatusBarButton object returned by statusItemObject.button() but as of writing there is no documentation for NSStatusBarButton, and the object returned is read-only and cannot be replaced with a custom button with overridden mouse event handlers.

有没有办法对附加到 NSStatusItem(或 NSStatusBarButton)的 NSMenu 是否显示鼠标事件进行某种程度的控制?

Is there a way to bring some level of control to whether an NSMenu attached to an NSStatusItem (or an NSStatusBarButton) is displayed with regard to mouse events?

推荐答案

这是我想出的解决方案.它工作得相当好,但有一点我不满意:在右键单击菜单中选择一个选项后,状态项会保持突出显示.一旦您与其他内容互动,亮点就会消失.

Here's the solution I came up with. It works fairly well, though there's one thing I'm not happy with: the status item stays highlighted after you choose an option in the right-click menu. The highlight goes away as soon as you interact with something else.

另请注意,popUpStatusItemMenu: 自 OS X 10.10 (Yosemite) 起已温和弃用",并将在未来版本中正式弃用.目前,它可以工作并且不会给您任何警告.希望在正式弃用之前,我们有一种完全受支持的方法来执行此操作 - 我建议提交错误报告如果你同意.

Also note that popUpStatusItemMenu: is "softly deprecated" as of OS X 10.10 (Yosemite), and will be formally deprecated in a future release. For now, it works and won't give you any warnings. Hopefully we'll have a fully supported way to do this before it's formally deprecated—I'd recommend filing a bug report if you agree.

首先你需要一些属性和一个枚举:

First you'll need a few properties and an enum:

typedef NS_ENUM(NSUInteger,JUNStatusItemActionType) {
    JUNStatusItemActionNone,
    JUNStatusItemActionPrimary,
    JUNStatusItemActionSecondary
};

@property (nonatomic, strong) NSStatusItem *statusItem;
@property (nonatomic, strong) NSMenu *statusItemMenu;
@property (nonatomic) JUNStatusItemActionType statusItemAction;

然后在某些时候您需要设置状态项:

Then at some point you'll want to set up the status item:

NSStatusItem *item = [[NSStatusBar systemStatusBar] statusItemWithLength:29.0];
NSStatusBarButton *button = item.button;
button.image = [NSImage imageNamed:@"Menu-Icon"];
button.target = self;
button.action = @selector(handleStatusItemAction:);
[button sendActionOn:(NSLeftMouseDownMask|NSRightMouseDownMask|NSLeftMouseUpMask|NSRightMouseUpMask)];
self.statusItem = item;

那么你只需要处理状态项按钮发送的动作:

Then you just need to handle the actions sent by the status item button:

- (void)handleStatusItemAction:(id)sender {

    const NSUInteger buttonMask = [NSEvent pressedMouseButtons];
    BOOL primaryDown = ((buttonMask & (1 << 0)) != 0);
    BOOL secondaryDown = ((buttonMask & (1 << 1)) != 0);
    // Treat a control-click as a secondary click
    if (primaryDown && ([NSEvent modifierFlags] & NSControlKeyMask)) {
        primaryDown = NO;
        secondaryDown = YES;
    }

    if (primaryDown) {
        self.statusItemAction = JUNStatusItemActionPrimary;
    } else if (secondaryDown) {
        self.statusItemAction = JUNStatusItemActionSecondary;
        if (self.statusItemMenu == nil) {
            NSMenu *menu = [[NSMenu alloc] initWithTitle:@""];
            [menu addItemWithTitle:NSLocalizedString(@"Quit",nil) action:@selector(terminate:) keyEquivalent:@""];
            self.statusItemMenu = menu;
        }
        [self.statusItem popUpStatusItemMenu:self.statusItemMenu];
    } else {
        self.statusItemAction = JUNStatusItemActionNone;
        if (self.statusItemAction == JUNStatusItemActionPrimary) {
            // TODO: add whatever you like for the primary action here
        }
    }

}

所以基本上,handleStatusItemAction: 在鼠标按下和鼠标抬起时为两个鼠标按钮调用.当按钮按下时,它会跟踪它应该执行主要操作还是次要操作.如果是次要操作,则会立即处理,因为菜单通常会在鼠标按下时出现.如果是主要操作,则在鼠标抬起时进行处理.

So basically, handleStatusItemAction: is called on mouse down and mouse up for both mouse buttons. When a button is down, it keeps track of whether it should do the primary or secondary action. If it's a secondary action, that's handled immediately, since menus normally appear on mouse down. If it's a primary action, that's handled on mouse up.

这篇关于Swift:10.10 中的 NSStatusItem 菜单行为(例如,仅在鼠标右键单击时显示)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆