NSSlider управления стрелками на NSMenu для NSStatusItem-Objective-C / Какао - PullRequest
1 голос
/ 17 октября 2011

Я хотел бы создать элемент состояния с вертикальным ползунком в нем, очень похоже на управление звуком, предоставляемое 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. Я просто не могу сделать это с помощью меню в строке состояния.

Ответы [ 2 ]

0 голосов
/ 05 августа 2013
- (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];
    }
}
0 голосов
/ 22 октября 2011

Я понял это. Apple использует подкласс NSWindow с именем NSCarbonMenuWindow для реализации меню. Итак, я получаю сообщение menuWillOpen: я немного жду, пока откроется меню, я получаю последнее окно (только что созданное - окно меню) и делаю ползунок первым ответчиком. Теперь все работает!

- (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];
    }    
}
...