views:

229

answers:

1

Hi,

I have an NSMenu that contains NSMenuItems with custom views. I want it so that when the alt button is pressed, the menu items would change part of their look (through their view). I found setAlternative in the NSMenuItem docs, however, in practice I could only get it to work with NSMenuItems without custom views. As soon as I set a custom view, all of the menu items would be displayed. Also, I tried getting keypress events while the menu was open. Due to the other run loop, NSApplication's sendEvent: doesn't receive events until after the menu is closed. Therefore, I can't just intercept the event coming in.

Does anyone know how I can get notified, whether through delegation or subclassing, of when the alt key is pressed when a menu is opened?

A: 

You should set an object as the delegate of your menu and then implement the delegate method -menu:updateItem:atIndex:shouldCancel:.

This will allow you to change the state of your custom view before the menu item is displayed, based on the current modifier state.

You can get the current modifiers by asking for [[NSApp currentEvent] modifierFlags].

If you need to be notified if the modifier flags change while your menu is open, implement the -flagsChanged: method in your custom view:

- (void)flagsChanged:(NSEvent*)event
{
    if ([event modifierFlags] & NSAlternateKeyMask)  // check for option key
    {
        //do something
    }
    else
    {
        //do something else
    }
}
Rob Keniger
I need it to happen when the menu is open. Like, not when the menu opens, but while it is open, if the user does key down with alt, then I need notification of it.
Nick Paulson
I've updated the answer with information about the `-flagsChanged` method.
Rob Keniger
I overrode -(BOOL)acceptsFirstResponder and -(BOOL)becomeFirstResponder to return YES in the custom view classes of my NSMenuItems. I then implemented flagsChanged:. I made the first menu item's view first responder when menuNeedsUpdate: However, flagsChanged: does not get called still. I also tried having it become responder after a 0.5 delay (in the tracking event loop mode), in case somehow the menu stole it back. That didn't work either. Any ideas?
Nick Paulson