19

我创建了一个简单NSStatusBarNSMenu菜单集。我还在NSMenuItems这个菜单中添加了一些,它们可以正常工作(包括选择器和突出显示),但是一旦我添加了自定义视图(setView :),就不会出现突出显示。

CustomMenuItem *menuItem = [[CustomMenuItem alloc] initWithTitle:@"" action:@selector(openPreferences:) keyEquivalent:@""];
[menuItem foo];
[menuItem setTarget:self];
[statusMenu insertItem:menuItem atIndex:0];
[menuItem release];

我的 foo 方法是:

- (void)foo {
  NSView *view = [[NSView alloc] initWithFrame:CGRectMake(5, 10, 100, 20)];
  [self setView:view];
}

如果我删除 setView 方法,它将突出显示。

我已经搜索和搜索,但找不到实现/启用此功能的方法。

编辑

我通过在我的 NSView 子类中遵循此问题中的代码来实现突出显示:

NSMenuItem 的视图(NSView 子类的实例)在悬停时未突出显示

#define menuItem ([self enclosingMenuItem])

- (void) drawRect: (NSRect) rect {
    BOOL isHighlighted = [menuItem isHighlighted];
    if (isHighlighted) {
        [[NSColor selectedMenuItemColor] set];
        [NSBezierPath fillRect:rect];
    } else {
        [super drawRect: rect];
    }
}
4

4 回答 4

10

这是上述内容的一个不那么冗长的版本。这对我来说效果很好。(backgroundColour 是一个 ivar。)

- (void)drawRect:(NSRect)rect
{
    if ([[self enclosingMenuItem] isHighlighted]) {
        [[NSColor selectedMenuItemColor] set];
    } else if (backgroundColour) {
        [backgroundColour set];
    }
    NSRectFill(rect);
}
于 2012-01-22T15:41:13.770 回答
8

2019 年更新:

class CustomMenuItemView: NSView {
    private var effectView: NSVisualEffectView

    override init(frame: NSRect) {
        effectView = NSVisualEffectView()
        effectView.state = .active
        effectView.material = .selection
        effectView.isEmphasized = true
        effectView.blendingMode = .behindWindow

        super.init(frame: frame)
        addSubview(effectView)
        effectView.frame = bounds
    }

    required init?(coder decoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func draw(_ dirtyRect: NSRect) {
        effectView.isHidden = !(enclosingMenuItem?.isHighlighted ?? false)
    }
}

将其中之一设置为您的menuItem.view.

(信用属于 Sam Soffes,他帮助我解决了这个问题,并几乎一字不差地给我发了那个代码。)

于 2019-05-22T03:43:17.320 回答
6

如果您要向菜单项添加视图,则该视图必须自己绘制突出显示。恐怕你不是免费得到的。从菜单编程主题

具有视图的菜单项不绘制其标题、状态、字体或其他标准绘图属性,而是将绘图职责完全分配给视图。

于 2011-05-19T06:00:36.697 回答
3

是的,如前所述,您必须自己绘制。我使用 AppKit 的 NSDrawThreePartImage(...) 进行绘制,还包括使用用户控件外观(蓝色或石墨)的检查。为了获取图像,我只是从屏幕截图中截取它们(如果有人知道更好的方法,请添加评论.) 这是我的 MenuItemView 的 drawRect 的一部分:

    // draw the highlight gradient
if ([[self menuItem] isHighlighted]) {

    NSInteger tint = [[NSUserDefaults standardUserDefaults] integerForKey:@"AppleAquaColorVariant"];
    NSImage *image = (AppleAquaColorGraphite == tint) ? menuItemFillGray : menuItemFillBlue;

    NSDrawThreePartImage(dirtyRect, nil, image, nil, NO,
        NSCompositeSourceOver, 1.0, [self isFlipped]);
}
else if ([self backgroundColor]) {

    [[self backgroundColor] set];
    NSRectFill(dirtyRect);
}

编辑

应该定义这些:

enum AppleAquaColorVariant {
    AppleAquaColorBlue = 1,
    AppleAquaColorGraphite = 6,
};

这些对应于系统偏好设置中的两个外观选项。此外,menuItemFillGray 和 menuItemFillBlue 只是标准菜单项填充渐变的 NSImage。

于 2011-05-20T10:29:43.047 回答