NSStatusBarButton keep highlighted

后端 未结 9 2380
一个人的身影
一个人的身影 2020-12-16 16:05

As of OS X 10.10 most of NSStatusItem has been deprecated in favour of the button property, which consists of an NSStatusBarButton. It should work like a norma

相关标签:
9条回答
  • 2020-12-16 16:54

    Struggling with this issue myself, I discovered that overwriting mouseDown: in a category on NSStatusBarButton works:

    #import "MUTargetClass.h"
    
    @implementation NSStatusBarButton (Additions)
    
    - (void)mouseDown:(NSEvent *)theEvent
    {
        // Relay CTRL+Click to perform a right click action
        if(theEvent.modifierFlags & NSControlKeyMask)
        {
            [self rightMouseDown:theEvent];
            return;
        }
    
        // Handle highlighting
        [self setHighlighted:YES];
    
        // Perform action on target
        [(MUTargetClass *)self.target actionSelector:self];
    }
    
    @end
    

    MUTargetClass could then for example implement:

    #import "NSStatusBarButton+Additions.h"
    
    @implementation MUTargetClass
    
    […]
        self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
        NSStatusBarButton *button = [self.statusItem button];
        [button setTarget:self];
    […]
    
    - (void)actionSelector:(id)sender
    {
        // Whatever behavior a click on the button should invoke
    }
    
    […]
        // Reset button's highlighting status when done
        [[self.statusItem button] setHighlighted:NO];
    […]
    
    @end
    

    Note that the functionality of CTRL+clicking the button is getting lost in the mouseDown: -override. As shown above, it can be restored by relaying the event to rightMouseDown:.

    A simpler way of having the action called would be something along the lines of [self.target performSelector:self.action] in the category and [self.statusItem setAction:@selector(actionSelector:)] in the target class, however this may cause a leak in ARC projects.

    Edit: This works on El Capitan, too.

    0 讨论(0)
  • 2020-12-16 16:54

    Anton's solution is perfect. Here it is in Swift 3:

    NSEvent.addLocalMonitorForEvents(matching: .leftMouseDown) { [weak self] event in
        if event.window == self?.statusItem.button?.window {
            // Your action:
            self?.togglePopover(self?.statusItem.button)
            return nil
        }
    
        return event
    }
    

    I added an observer for NSApplicationWillResignActive to close the popover and set the button's isHighlighted to false.

    0 讨论(0)
  • 2020-12-16 16:56

    I added a subview to the status item, and inside that view I added event handlers for mouseDown etc. which called [[statusItem button] highlight:true]. As it turns out setHighlighted: doesn't do the same thing as highlight:.

    NSArray *array = [NSArray arrayWithObjects:[statusItem button], [self statusItemView], nil];
    [[[statusItem button] superview] setSubviews:array];
    //Highlight like so:
    [[statusItem button] highlight:true];
    

    EDIT: As of El Capitan this method no longer works, and neither does statusItem.button.highlight = true either

    0 讨论(0)
提交回复
热议问题