Как я уже прокомментировал, я нахожу пример ButtonMadness менее совершенным.
Моя реализация, кажется, работает лучше. Меню отображается при наведении мыши, кнопка остается нажатой в течение всего времени, позиция меню может быть задана, и меню закрывается без последующего ложного отображения.
Если честно, NSPopupButton - лучший выбор в большинстве ситуаций. Я использую этот код в основном из-за удобства наличия одного класса для кнопок и всплывающих окон, а также потому, что в меню нет изображения и заголовка всплывающего элемента управления. Я загружаю меню из отдельного пера и повторно использую его, как и в любом другом месте приложения.
Обратите внимание, что добавить дополнительную поддержку, например, для всплывающих окон и меню, довольно просто.
NSButton subclass:
- (void)mouseDown:(NSEvent *)theEvent {
// if a menu is defined let the cell handle its display
if (self.menu) {
if ([theEvent type] == NSLeftMouseDown) {
[[self cell] setMenu:[self menu]];
} else {
[[self cell] setMenu:nil];
}
}
[super mouseDown:theEvent];
}
NSButtonCell subclass:
- (BOOL)trackMouse:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp
{
// if menu defined show on left mouse
if ([event type] == NSLeftMouseDown && [self menu]) {
NSPoint result = [controlView convertPoint:NSMakePoint(NSMidX(cellFrame), NSMidY(cellFrame)) toView:nil];
NSEvent *newEvent = [NSEvent mouseEventWithType: [event type]
location: result
modifierFlags: [event modifierFlags]
timestamp: [event timestamp]
windowNumber: [event windowNumber]
context: [event context]
eventNumber: [event eventNumber]
clickCount: [event clickCount]
pressure: [event pressure]];
// need to generate a new event otherwise selection of button
// after menu display fails
[NSMenu popUpContextMenu:[self menu] withEvent:newEvent forView:controlView];
return YES;
}
return [super trackMouse:event inRect:cellFrame ofView:controlView untilMouseUp:untilMouseUp];
}