1

我想创建一个带有垂直滑块的状态项,就像 Apple 提供的声音控制一样。我的问题是:我如何让它对向上/向下箭头键做出反应,就像声音菜单中的滑块一样?

我试图创建一个 NSSlider 子类,当按键被按下时会增加/减少它的值(见下文),但我需要让它成为第一响应者。为了使它成为第一响应者,我将主类设置为这个菜单的代表并添加了这个方法:

- (void)menuWillOpen: (NSMenu*)menu
{
    if (menu == statusBarMenu) {        
        [THE_WINDOW_THAT_CONTAINS_THE_SLIDER makeFirstResponder: slider];
}

我应该调用哪个窗口?我应该以其他方式这样做吗?你会怎么做?

滑块子类:

#import <AppKit/AppKit.h>

@interface KeyRespondingSlider : NSSlider

@end

@implementation KeyRespondingSlider

- (BOOL)canBecomeKeyView
{
    return YES;
}
- (BOOL)acceptsFirstResponder
{
    return YES;
}

- (void)keyDown: (NSEvent*)theEvent
{
    unsigned short keyCode = [theEvent keyCode];
    if (keyCode == 126) { // up-arrow
        [self setDoubleValue: [self doubleValue] + kChange];
    }
    else if (keyCode == 125) { // down-arrow
        [self setDoubleValue: [self doubleValue] - kChange];
    }
}

@end

我已经对其进行了测试,当它是具有正常 NSWindow 的第一响应者时它可以工作。我只是不能用状态栏项目中的菜单来做到这一点。

4

2 回答 2

0

我已经想通了。Apple 使用一个 NSWindow 子类NSCarbonMenuWindow来实现菜单。所以我得到了 menuWillOpen: 消息,我稍等了一会儿菜单打开,我得到了最后一个窗口(刚刚创建的那个 - 菜单窗口),并将滑块设置为 firstResponder。现在一切正常!

- (void)menuWillOpen: (NSMenu*)menu
{
    if (menu == statusBarMenu) {
        [NSThread detachNewThreadSelector: @selector(threadedMenuWillOpen) toTarget: self withObject: nil];
    }
}

- (void)threadedMenuWillOpen
{
    [NSThread sleepForTimeInterval: 0.1];

    NSArray* windows = [NSApp windows];
    NSWindow* menuWindow = [windows lastObject]; // The last window is the one I want because it has just been created

    if ([[menuWindow className] isEqualToString: @"NSCarbonMenuWindow"]) {
        [menuWindow makeFirstResponder: bSlider];
    }    
}
于 2011-10-22T07:58:30.640 回答
0
- (void)keyDown: (NSEvent*)theEvent
{
    unsigned short keyCode = [theEvent keyCode];
    if (keyCode == 126) { // up-arrow
        [[NSNotificationCenter defaultCenter] postNotificationName:@"upArrow" object:nil];
    }
    else if (keyCode == 125) { // down-arrow
        [[NSNotificationCenter defaultCenter] postNotificationName:@"DownArrow" object:nil];
    } else
    {
        [super keyDown:theEvent];
    }
}
于 2013-08-05T16:27:42.250 回答