显示弹出窗口时保持NSStatusBarButton突出显示

时间:2015-07-18 21:27:48

标签: objective-c macos cocoa osx-yosemite nsstatusitem

实际上,所有NSStatusItem都已弃用10.10,基础NSStatusBarButton的行为似乎令人困惑。

目前我正在开发一个菜单栏应用程序。当用户单击应用程序的菜单栏图标时,我的应用程序委托中的方法将通过target-action调用,该方法显示NSPopover(如果已经可见,则显示NSPopover)以及某些信息。

通常情况下,如果您使用NSStatusItem关联NSMenu,当用户点击菜单栏图标时图标仍然以蓝色突出显示为蓝色,直到菜单关闭为止。同样,单击系统音量图标会弹出一个滑块并将其图标突出显示为蓝色,直到包含滑块的视图消失。

但是,由于我打开了NSPopover,系统会在鼠标按下时突出显示蓝色图标,然后在调用方法后将鼠标向上恢复正常。这意味着我在循环中似乎没有什么可以保持突出显示。我希望图标继续在鼠标上突出显示,并且只有当我告诉它时才会恢复正常(即,当我关闭我的弹出窗口时。)

我不知道该怎么做。我尝试过使用

[self.statusItem.button setHighlighted: YES];
//or [self.statusItem.button highlight: YES];

当我在我的app delegate中收到鼠标注册事件并打开popover时。问题是系统仍然有它,显然,从早期鼠标向下突出显示此帧/循环,并在我将其设置为突出显示后立即将其设置为由于鼠标向上而不突出显示。我可以通过将其封装在一个方法中并在一瞬间使用计时器或延迟选择器运行该方法来解决这个问题。这允许我保持图标突出显示但引入闪烁;当鼠标向下移动时,图标会自动突出显示,当鼠标向上移动时,它会突出显示一帧,然后我的方法会重新突出显示它。

我还想也许我可以使用已弃用的setHighlightMode:并将其设置为NO以防止图标在点击时自动突出显示,然后使用setHighlighted: / highlighted:手动设置它,但是也不起作用。同样,我想也许这也会有用:

 NSButtonCell* cell = (NSButtonCell*)self.statusItem.button.cell;
cell.highlightsBy = NSNoCellMask;

但无论点击它是否会自动突出显示图标,并在我的方法被调用后立即在鼠标上取消它。

基本上:

  
      
  1. NSStatusBarButton的不良自动突出显示行为会干扰手动设置突出显示状态,除非我延迟手动设置它会引入短暂的闪烁。
  2.   
  3. 似乎唯一成功禁用此自动行为的是弃用的setHighlightMode:,但这似乎可以防止所有突出显示,无论是否手动。
  4.   
  5. 唯一的解决方法似乎是向NSButtonCell添加子视图,为鼠标添加一个事件监听器,然后按照此处设置superview的高亮状态:   NSStatusBarButton keep highlighted   但我认为这只是一种更简单的方法......完全禁用自动突出显示。
  6.   

tl;博士:有没有办法让我轻松获得对我的菜单栏图标突出显示的时间和时间的完全控制,这样我可以在显示NSPopover时自然突出显示它?

1 个答案:

答案 0 :(得分:7)

我最后通过不设置NSStatusItem的动作选择器属性来解决这个问题。相反,我使用了NSEvent' s addLocalMonitorForEventsMatchingMask:handler:。在处理程序块中,我检查event.locationInWindow是否在我的状态项.bounds内。如果是这样,我会发送.action手动发送的消息,然后返回nil以防止事件被传递。如果它不在状态图标的范围内,则返回event,以便正常传递。在我的点击处理方法中,当我的弹出窗口显示/关闭时,我使用[self.statusItem.button highlight: YES/NO]

TL; DR:

applicationDidFinishLaunching:

__block AppDelegate* appDelegate = self;
[NSEvent addLocalMonitorForEventsMatchingMask: NSEventMaskFromType(NSLeftMouseDown) handler:^NSEvent* (NSEvent* event){
    if (NSPointInRect(event.locationInWindow, appDelegate.statusItem.button.bounds)){
        [appDelegate clickedMenuBarIcon: event];
        return nil;
    }
    return event;
 }];

clickedMenuBarIcon:中我可以设置突出显示状态。由于我在处理程序块中返回nil,因此阻止事件传递,因此自动突出显示永远不会发生,我可以手动执行。

如果有任何与此相关的错误,我会感激任何建议。