3

我在一个非常键盘密集型的应用程序上工作。双手放在键盘上。没有手放在鼠标上。

用户可以通过键盘弹出上下文菜单,选择一个项目,最后按 Enter。

[NSMenu popUpContextMenu]显示菜单而不突出显示任何项目。用户必须按一次 arrow_down 才能突出显示第一项。

我的一位朋友观察到每次使用此菜单时都必须按 arrow_down,并建议我删除此步骤,以便在弹出菜单时始终突出显示第一项。

我怀疑它需要碳破解?

如何以编程方式突出显示第一项?


我使用此代码弹出一个菜单。

NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined
    location:location 
    modifierFlags:0 
    timestamp:0
    windowNumber:[[self window] windowNumber]
    context:[[self window] graphicsContext]
    subtype:100
    data1:0
    data2:0
];
[NSMenu popUpContextMenu:menu withEvent:event forView:self];

更新:我尝试在 popUpContextMenu 之后立即向我的应用发送一个 arrow_down 事件,但是当菜单可见时该事件不会执行。(该事件在菜单消失后执行)。

unichar code = NSDownArrowFunctionKey;
NSString* chars = [NSString stringWithFormat: @"%C", code];
NSEvent* event = [NSEvent keyEventWithType:NSKeyDown location:location modifierFlags:0 timestamp:0 windowNumber:[[self window] windowNumber] context:[[self window] graphicsContext] characters:chars charactersIgnoringModifiers:chars isARepeat:NO keyCode:code];
[NSApp sendEvent:event];
4

2 回答 2

0

我找到了原始问题的答案。但是它有问题,我认为_NSGetCarbonMenu()有必要解决它们。

  1. 问题:如何绘制菜单项使其看起来像原生菜单项?
  2. 问题:如何使自定义视图表现得像一个普通的菜单项。现在你必须按两次箭头来选择下一个项目。

如何解决这些问题?

@interface MyMenuItem : NSView {
    BOOL m_active;
}
@end

@implementation MyMenuItem
- (BOOL)acceptsFirstResponder { return YES; }
- (BOOL)becomeFirstResponder { m_active = YES; return YES; }
- (BOOL)resignFirstResponder { m_active = NO; return YES; }

- (void)viewDidMoveToWindow { [[self window] makeFirstResponder:self]; }

- (void)drawRect:(NSRect)rect {
    if(m_active) {
        [[NSColor blueColor] set];
    } else {
        [[NSColor blackColor] set];
    }
    NSRectFill(rect);
}
@end


// this makes sure the first item gets selected when the menu popups
MyMenuItem* view = [[[MyMenuItem alloc] initWithFrame:NSMakeRect(0, 0, 100, 20)] autorelease];
[view setAutoresizingMask:NSViewWidthSizable];
NSMenuItem* item = [menu itemAtIndex:0];
[item setView:view];
[NSMenu popUpContextMenu:menu withEvent:event forView:self];

解决了!忘记上面的所有东西。我刚刚找到了一个完全不需要 Carbon 的优雅解决方案。

// simulate a key press of the arrow-down key
CGKeyCode key_code = 125;  // kVK_DownArrow = 125
CGEventRef event1, event2;
event1 = CGEventCreateKeyboardEvent(NULL, key_code, YES);
event2 = CGEventCreateKeyboardEvent(NULL, key_code, NO);
CGEventPost(kCGSessionEventTap, event1);
CGEventPost(kCGSessionEventTap, event2);
CFRelease(event1);
CFRelease(event2);

[NSMenu popUpContextMenu:menu withEvent:event forView:self];
于 2010-07-07T21:36:36.363 回答
0

作为记录,如果您的目标是 10.6 及更高版本,请不要使用类方法popUpContextMenu,使用实例的popUpMenuPositioningItem:atLocation:inView:. 如果您指定positioningItem它将被自动选择。当然,您需要重新计算相对于所选项目的位置。

于 2015-11-06T23:01:51.957 回答