Right-click menu NSStatusItem

I am working on a status application that has a left and right click. I have the beginning of this work, following the advice of other posts, but I'm not sure how to proceed to display the menu with a right click.

I use a subclassified NSView as a custom view of my NSStatusItem and have right and left clicks that perform different functions:

- (void)mouseDown:(NSEvent *)theEvent{ [super mouseDown:theEvent]; if ([theEvent modifierFlags] & NSCommandKeyMask){ [self.target performSelectorOnMainThread:self.rightAction withObject:nil waitUntilDone:NO]; }else{ [self.target performSelectorOnMainThread:self.action withObject:nil waitUntilDone:NO]; } } - (void)rightMouseDown:(NSEvent *)theEvent{ [super rightMouseDown:theEvent]; [self.target performSelectorOnMainThread:self.rightAction withObject:nil waitUntilDone:NO]; } 

How can I show the menu with the right mouse button, just as the standard NSStatusItem does on the left click?

+4
source share
3 answers

NSStatusItem popUpStatusItemMenu: did the trick. I call it from my action with the right mouse button and pass it to the menu that I want to show, and it shows it! This is not what I would expect from this function, but it works.

Here are the important parts of what my code looks like:

 - (void)showMenu{ // check if we are showing the highlighted state of the custom status item view if(self.statusItemView.clicked){ // show the right click menu [self.statusItem popUpStatusItemMenu:self.rightClickMenu]; } } // menu delegate method to unhighlight the custom status bar item view - (void)menuDidClose:(NSMenu *)menu{ [self.statusItemView setHighlightState:NO]; } - (void)applicationDidFinishLaunching:(NSNotification *)aNotification{ // setup custom view that implements mouseDown: and rightMouseDown: self.statusItemView = [[ISStatusItemView alloc] init]; self.statusItemView.image = [NSImage imageNamed:@"menu.png"]; self.statusItemView.alternateImage = [NSImage imageNamed:@"menu_alt.png"]; self.statusItemView.target = self; self.statusItemView.action = @selector(mainAction); self.statusItemView.rightAction = @selector(showMenu); // set menu delegate [self.rightClickMenu setDelegate:self]; // use the custom view in the status bar item self.statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength]; [self.statusItem setView:self.statusItemView]; } 

Here is the implementation for custom view:

 @implementation ISStatusItemView @synthesize image = _image; @synthesize alternateImage = _alternateImage; @synthesize clicked = _clicked; @synthesize action = _action; @synthesize rightAction = _rightAction; @synthesize target = _target; - (void)setHighlightState:(BOOL)state{ if(self.clicked != state){ self.clicked = state; [self setNeedsDisplay:YES]; } } - (void)drawImage:(NSImage *)aImage centeredInRect:(NSRect)aRect{ NSRect imageRect = NSMakeRect((CGFloat)round(aRect.size.width*0.5f-aImage.size.width*0.5f), (CGFloat)round(aRect.size.height*0.5f-aImage.size.height*0.5f), aImage.size.width, aImage.size.height); [aImage drawInRect:imageRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f]; } - (void)drawRect:(NSRect)rect{ if(self.clicked){ [[NSColor selectedMenuItemColor] set]; NSRectFill(rect); if(self.alternateImage){ [self drawImage:self.alternateImage centeredInRect:rect]; }else if(self.image){ [self drawImage:self.image centeredInRect:rect]; } }else if(self.image){ [self drawImage:self.image centeredInRect:rect]; } } - (void)mouseDown:(NSEvent *)theEvent{ [super mouseDown:theEvent]; [self setHighlightState:!self.clicked]; if ([theEvent modifierFlags] & NSCommandKeyMask){ [self.target performSelectorOnMainThread:self.rightAction withObject:nil waitUntilDone:NO]; }else{ [self.target performSelectorOnMainThread:self.action withObject:nil waitUntilDone:NO]; } } - (void)rightMouseDown:(NSEvent *)theEvent{ [super rightMouseDown:theEvent]; [self setHighlightState:!self.clicked]; [self.target performSelectorOnMainThread:self.rightAction withObject:nil waitUntilDone:NO]; } - (void)dealloc{ self.target = nil; self.action = nil; self.rightAction = nil; [super dealloc]; } @end 
+19
source

One option is to simply fake the left mouse button down:

 - (void)rightMouseDown: (NSEvent *)event { NSEvent * newEvent; newEvent = [NSEvent mouseEventWithType:NSLeftMouseDown location:[event locationInWindow] modifierFlags:[event modifierFlags] timestamp:CFAbsoluteTimeGetCurrent() windowNumber:[event windowNumber] context:[event context] eventNumber:[event eventNumber] clickCount:[event clickCount] pressure:[event pressure]]; [self mouseDown:newEvent]; } 
+3
source

Added a little something when you need a title in your view

 - (void)drawRect:(NSRect)rect{ if(self.clicked){ [[NSColor selectedMenuItemColor] set]; NSRectFill(rect); if(self.alternateImage){ [self drawImage:self.alternateImage centeredInRect:rect]; }else if(self.image){ [self drawImage:self.image centeredInRect:rect]; } else { [self drawTitleInRect:rect]; } } else if(self.image){ [self drawImage:self.image centeredInRect:rect]; } else { [self drawTitleInRect:rect]; } } -(void)drawTitleInRect:(CGRect)rect { CGSize size = [_title sizeWithAttributes:nil]; CGRect newRect = CGRectMake(MAX((rect.size.width - size.width)/2.f,0.f), MAX((rect.size.height - size.height)/2.f,0.f), size.width, size.height); NSDictionary *attributes = @{NSForegroundColorAttributeName : self.clicked?[NSColor highlightColor]:[NSColor textColor] }; [_title drawInRect:newRect withAttributes:attributes]; } 
0
source

All Articles