目标c-单击后从NSMenuItem中删除高亮显示



我为NSMenuItem的子类(位于NSStatusMenu中)添加了一个自定义视图,这意味着默认情况下它不会以蓝色/灰色背景"突出显示"。

我使用以下代码实现了这一点:

- (void)drawRect:(NSRect)rect {
  BOOL isHighlighted = [menuItem isHighlighted];
  if (isHighlighted) {
    [[NSColor selectedMenuItemColor] set];
    [NSBezierPath fillRect:rect];
    [menuItem addHover];
  } else {
    [super drawRect:rect];
    [menuItem removeHover];
  }
}
- (void)mouseUp:(NSEvent*)event {
  NSMenuItem *item = [self enclosingMenuItem];
  NSMenu *menu = [item menu];
  [menu cancelTracking];
  [menu performActionForItemAtIndex:[menu indexOfItem:item]];
}

菜单项高亮显示得很好,我也可以点击每个项目;然而,当我点击它们时,一旦我重新打开菜单,它们似乎会保持isHighlighted状态。

有没有办法更改它,这样当我单击时,下次打开菜单时高亮显示的状态就会被删除?

我突然想到,我们必须这样做,而不是简单的NSMenuItem setHighlighted或NSMenu removeHighlights之类的。这是一个片段,看起来很像沃克先生的回答。。它只是从菜单中删除您自己的菜单项,然后将其放回原处。

    NSMenuItem *selfmi = [self enclosingMenuItem];
    NSMenu* menu = [[self enclosingMenuItem] menu];
    int i = [menu indexOfItem:selfmi];
    [menu removeItemAtIndex:i];
    [menu insertItem:selfmi atIndex:i];

我在自定义视图中删除了mouseUp方法,然后在其中添加了另一个"隐藏"NSView,它具有以下方法:

- (BOOL)acceptsFirstResponder {
  NSMenu *menu = [item menu];
  [menu cancelTracking];
  [menu performActionForItemAtIndex:[menu indexOfItem:item]];
  return YES;
}

我的解决方案是在cancelTracking:之后删除并重新添加菜单项

- (void)mouseUp:(NSEvent*)event {
  NSMenuItem *item = [self enclosingMenuItem];      
  NSMenu *menu = [item menu];      
  if (nil != menu) {
      NSInteger index = [menu indexOfItem:item];      
      [menu cancelTracking];        
      [menu performActionForItemAtIndex:index];
      // hack to reset highlighted menu item state
      NSArray *items = [menu itemArray];
      [menu removeAllItems];
      for (NSMenuItem *item in items) {
          [menu addItem:item];
      }
  }
}    

我在应用程序的主菜单中遇到了一个独特的情况,删除和重新添加菜单项并没有删除菜单项的突出部分。这是我用来删除高亮显示的Swift函数,添加一个伪菜单项,"点击"它,然后删除伪菜单项:

func unhighlightItems(in menu: NSMenu) {
    let dummyItem = NSMenuItem(title: "", action: nil, keyEquivalent: "")
    menu.addItem(dummyItem)
    menu.performActionForItem(at: mainMenu.index(of: dummyItem))
    menu.removeItem(dummyItem)
}

最新更新