Какао: щелкните правой кнопкой мыши NSStatusItem

Я .Net-разработчик, которому нужно портировать небольшой проект на Mac, поэтому я почти ничего не знаю об Objective C. На самом деле приведенный ниже код был просто набором хватаний за соломинку и стрельбы в темноте.

Попытка создать программу меню состояния, которая открывает то или иное окно в зависимости от того, щелчок левой кнопкой мыши или щелчок правой кнопкой мыши / ctrl + щелчок. Вот что у меня есть, и это работает только для щелчка левой кнопкой мыши (очевидно):

-(void) awakeFromNib{

    NSBundle *bundle = [NSbundle mainBundle];

    statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain];
    [statusImage = [[NSImage alloc] initWithContentsOfFile:[bundle pathForResource:@"icon" ofType:@"png"]];
    [statusItem setImage:statusImage];
    [statusItem setToolTip:@"Program Name"];
    [statusItem setHighlightMode:YES];
    [statusItem setAction:@selector(openWin:)];
    [statusItem setTarget: self];
}

-(void)openWin:(id)sender{
    [self openLeftWindow:sender];
}

-(IBAction)openLeftWindow:(id)sender{
    //Code to populate Left Click Window
    [leftWindow makeKeyAndorderFront:nil];
}

-(IBAction)openRightWindow:(id)sender{
    //Code to populate Right Click Window
    [rightWindow makeKeyAndorderFront:nil];
}

Мне кажется, что решением будет либо оператор if в функции openWin(), чтобы определить, какая кнопка нажата (или удерживается ли ctrl), затем запустить соответствующий код, либо чтобы меню знало как о левом, так и о правом клики. Но ни один из них не работал, когда я пытался это сделать.

Заранее спасибо.


person Dan    schedule 30.12.2010    source источник
comment
Я предполагаю, что это просто опечатка, что методы openLeftWindow: и openRightWindow: делают одно и то же. В противном случае этот вопрос был бы бесполезен.   -  person ughoavgfhw    schedule 30.12.2010
comment
Правильно, они делают разные вещи. Извините за опечатку   -  person Dan    schedule 30.12.2010


Ответы (3)


Если вы будете удовлетворены обнаружением щелчка мышью, а не щелчка правой кнопкой мыши, тогда первый блок кода будет делать то, что вы хотите. Если вам действительно нужно обнаружение правого щелчка, вам придется использовать пользовательское представление вместо изображения в вашем NSStatusItem, и второй блок кода будет работать.

Простой метод:

- (void)openWin:(id)sender {
    NSEvent *event = [NSApp currentEvent];
    if([event modifierFlags] & NSControlKeyMask) {
        [self openRightWindow:nil];
    } else {
        [self openLeftWindow:nil];
    }
}

Пользовательский метод просмотра:

- (void)awakeFromNib {
    ...
    statusImage = ...
    MyView *view = [MyView new];
    view.image = statusImage;
    [statusItem setView:view];
    [statusItem setToolTip:@"Program Name"];
    view target = self;
    view action = @selector(openLeftWindow:);
    view rightAction = @selector(openRightWindow:);
    [view release];
    //[statusImage release]; //If you are not using it anymore, you should release it.
}

MyView.h

#import <Cocoa/Cocoa.h>
@interface MyView : NSControl {
    NSImage *image;
    id target;
    SEL action, rightAction;
}
@property (retain) NSImage *image;
@property (assign) id target;
@property (assign) SEL action, rightAction;
@end

MyView.m

#import "MyView.h"
@implementation MyView
@synthesize image, target, action, rightAction;
- (void)mouseUp:(NSEvent *)event {
    if([event modifierFlags] & NSControlKeyMask) {
        [NSApp sendAction:self.rightAction to:self.target from:self];
    } else {
        [NSApp sendAction:self.action to:self.target from:self];
    }
}
- (void)rightMouseUp:(NSEvent *)event {
    [NSApp sendAction:self.rightAction to:self.target from:self];
}
- (void)dealloc {
    self.image = nil;
    [super dealloc];
}
- (void)drawRect:(NSRect)rect {
    [self.image drawInRect:self.bounds fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];
}
@end
person ughoavgfhw    schedule 30.12.2010
comment
Это второе решение именно то, что я хочу. Но значок не появляется в строке состояния. Я могу щелкнуть (влево, вправо и ctrl) там, где должен быть значок, и он отлично работает, но сам значок отсутствует. - person Dan; 31.12.2010
comment
Извините, я забыл добавить метод drawRect:. Я добавлю его в свой пост. - person ughoavgfhw; 31.12.2010
comment
После ручной настройки размера значка это сработало отлично! Спасибо! - person Dan; 03.01.2011
comment
Хммм... теперь небольшая проблема. В открывшемся окне есть ссылки и команды для запуска внешних программ и веб-сайтов. Когда я нажимаю на эти ссылки и кнопки, значок исчезает, даже если я нажимаю в области, которой принадлежит значок, он все еще ведет себя. Почти как проблема раньше, но теперь изображение есть изначально, но не сохраняется, когда я использую ссылки/кнопки, открывающие внешний контент. - person Dan; 03.01.2011
comment
Похоже, вид перерисовывается без перерисовки. Попробуйте пометить его как требующий отображения всякий раз, когда вы обрабатываете ссылку или нажатие кнопки. - person ughoavgfhw; 03.01.2011
comment
Любые намеки на то, как это делается. Я провел последние три часа, пытаясь понять это. - person Dan; 04.01.2011
comment
Это блестяще, работает отлично, как описано. Одна вещь, с которой я все еще борюсь, - это заставить меню состояния nsmenu отображаться при щелчке правой кнопкой мыши, есть идеи? - person Dom Vinyard; 04.12.2012
comment
@Atheist Предполагая, что вы используете подход с представлением, вы можете попробовать использовать метод menuForEvent: в своем представлении, чтобы вернуть меню, но я не знаю, будет ли он работать должным образом в элементе состояния. Если нет, вам нужно будет использовать метод rightMouseUp: и вызвать popUpContextMenu:withEvent:forView:, чтобы отобразить меню вручную. - person ughoavgfhw; 04.12.2012

Я бы создал представление и использовал метод элементов состояния.

-setView:

Затем в представлении подкласса вы можете обнаружить ctrl+LMB, используя следующие

- (void)mouseDown:(NSEvent *)theEvent
{
    [super mouseDown:theEvent];

    //Respond to the mouse click
    if ([theEvent modifierFlags] & NSCommandKeyMask) //Command + LMB
    {       
      //Do something
    }
}

Я думаю, вы можете понять остальное.

person David    schedule 30.12.2010

Более упрощенный ответ (обратите внимание, работает только с управлением + клик)

Характеристики:

@property (strong, nonatomic) NSStatusItem *statusItem;
@property (weak) IBOutlet NSMenu *statusMenu;

В вашем приложении загружено:

[self.statusItem setAction:@selector(itemClicked:)];

Нажатая функция:

- (void)itemClicked:(id)sender
{
    NSEvent *event = [NSApp currentEvent];

    if([event modifierFlags] & NSControlKeyMask) {
        NSLog(@"Right Click Pressed");
        [self.statusItem popUpStatusItemMenu:self.statusMenu];

    } else {
        // Do Nothing
        NSLog(@"Left Click Pressed");
    }
}
person James Marino    schedule 16.08.2015