NSMenu突出显示特定的NSMenuItem

时间:2015-08-13 13:42:39

标签: macos cocoa nsmenu nsmenuitem

如何突出显示特定的NSMenuItemhighlightedItem上只有NSMenu方法,但没有setHighlightedItem

1 个答案:

答案 0 :(得分:1)

<强>更新

浏览OS X Runtime headers我在NSMenu找到了另一种方法,它不需要获取Carbon菜单实现。 该方法称为highlightItem:,可以按预期工作。

基本上,NSMenu类别可以简化为以下内容:

@interface NSMenu (HighlightItemUsingPrivateAPIs)

- (void)_highlightItem:(NSMenuItem*)menuItem;

@end

@implementation NSMenu (HighlightItemUsingPrivateAPIs)

- (void)_highlightItem:(NSMenuItem*)menuItem
{
    const SEL selHighlightItem = @selector(highlightItem:);

    if ([self respondsToSelector:selHighlightItem]) {
        [self performSelector:selHighlightItem withObject:menuItem];
    }
}

@end

原始回答

虽然似乎没有这样做的官方方式,但可以使用私有(!)API。

这是我为NSMenu撰写的一个类别,它允许您突出显示特定索引处的项目:

@interface NSMenu (HighlightItemUsingPrivateAPIs)

- (void)_highlightItemAtIndex:(NSInteger)index;

@end

@implementation NSMenu (HighlightItemUsingPrivateAPIs)

- (void)_highlightItemAtIndex:(NSInteger)index
{
    const SEL selMenuImpl = @selector(_menuImpl);

    if ([self respondsToSelector:selMenuImpl]) {
        id menuImpl = [self performSelector:selMenuImpl];

        const SEL selHighlightItemAtIndex = @selector(highlightItemAtIndex:);

        if (menuImpl &&
            [menuImpl respondsToSelector:selHighlightItemAtIndex]) {
            NSMethodSignature* signature = [[menuImpl class] instanceMethodSignatureForSelector:selHighlightItemAtIndex];

            NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:signature];
            [invocation setTarget:menuImpl];
            [invocation setSelector:selHighlightItemAtIndex];
            [invocation setArgument:&index atIndex:2];
            [invocation invoke];
        }
    }
}

@end

首先,它获取NSCarbonMenuImpl的Carbon菜单实现(NSMenu),然后使用指定的索引继续调用highlightItemAtIndex:。如果Apple决定更改此处使用的私有API,则该类别的编写方式会优雅地失败。