2010-10-31 3 views
1

Я хочу создать меню для элемента строки состояния, как один замеченный в применении PastebotSync Tapbot в:Обратное проектирование в NSMenu для Status Bar Пункт

Кто-нибудь есть какие-либо идеи, как достичь пользовательской области в верхней части меню, которая находится на одном уровне с верхней частью?

Я попытался/мысль несколько возможных способов сделать это:

  • Стандартный NSMenuItem с видом - не заподлицо с верхней части меню
  • Некоторые хак-иш код поместите NSWindow над областью в верхней части меню - не очень хорошо, поскольку она не исчезает красиво с меню, когда оно закрывается
  • Отказ от NSMenu полностью и использование NSView вместо этого - еще не пробовал это, но я на самом деле не хотят делать какие-то поддельные кнопки или что-то, что действует как NSMenuItems

У кого-нибудь есть лучшие идеи или предложения?

Спасибо!

ответ

4

В случае, если кто приходит смотрит, я отправил решение к этому в Gap above NSMenuItem custom view

Вот код:

@interface FullMenuItemView : NSView 
@end 

@implementation FullMenuItemView 
- (void) drawRect:(NSRect)dirtyRect 
{ 
    NSRect fullBounds = [self bounds]; 
    fullBounds.size.height += 4; 
    [[NSBezierPath bezierPathWithRect:fullBounds] setClip]; 

    // Then do your drawing, for example... 
    [[NSColor blueColor] set]; 
    NSRectFill(fullBounds); 
} 
@end 

Используйте это так:

CGFloat menuItemHeight = 32; 

NSRect viewRect = NSMakeRect(0, 0, /* width autoresizes */ 1, menuItemHeight); 
NSView *menuItemView = [[[FullMenuItemView alloc] initWithFrame:viewRect] autorelease]; 
menuItemView.autoresizingMask = NSViewWidthSizable; 

yourMenuItem.view = menuItemView; 
1

У меня была такая же потребность в ранних версиях HoudahSpot 2. Я работал с одним ограничением: мой код покидает меню с квадратными углами внизу.

С тех пор я отказался от этой установки, так как функция BlitzSearch в HoudahSpot выросла, чтобы потребоваться сложный интерфейс, я столкнулся с другими ограничениями с использованием NSViews в NSMenu.

Во всяком случае, здесь исходный код заботиться о тех дополнительных 3 пикселя:

- (void)awakeFromNib 
{ 
HIViewRef contentView; 
MenuRef menuRef = [statusMenu carbonMenuRef]; 
HIMenuGetContentView (menuRef, kThemeMenuTypePullDown, &contentView); 

EventTypeSpec hsEventSpec[1] = { 
    { kEventClassMenu, kEventMenuCreateFrameView } 
}; 

HIViewInstallEventHandler(contentView, 
      NewEventHandlerUPP((EventHandlerProcPtr)hsMenuCreationEventHandler), 
      GetEventTypeCount(hsEventSpec), 
      hsEventSpec, 
      NULL, 
      NULL); 
} 


#pragma mark - 
#pragma mark Carbon handlers 

static OSStatus hsMenuContentEventHandler(EventHandlerCallRef caller, EventRef event, void* refcon) 
{ 
OSStatus err; 

check(GetEventClass(event) == kEventClassControl); 
check(GetEventKind(event) == kEventControlGetFrameMetrics); 

err = CallNextEventHandler(caller, event); 
if (err == noErr) 
{ 
    HIViewFrameMetrics metrics; 

    verify_noerr(GetEventParameter(event, kEventParamControlFrameMetrics, typeControlFrameMetrics, NULL, 
      sizeof(metrics), NULL, &metrics)); 

    metrics.top = 0; 

    verify_noerr(SetEventParameter(event, kEventParamControlFrameMetrics, typeControlFrameMetrics, 
      sizeof(metrics), &metrics)); 
} 

return err; 
} 

static OSStatus hsMenuCreationEventHandler(EventHandlerCallRef caller, EventRef event, void* refcon) 
{ 
OSStatus err = eventNotHandledErr; 

if (GetEventKind(event) == kEventMenuCreateFrameView) 
{ 
    err = CallNextEventHandler(caller, event); 
    if (err == noErr) 
    { 
    static const EventTypeSpec kContentEvents[] = 
    { 
    { kEventClassControl, kEventControlGetFrameMetrics } 
    }; 

    HIViewRef   frame; 
    HIViewRef   content; 

    verify_noerr(GetEventParameter(event, kEventParamMenuFrameView, typeControlRef, NULL, 
      sizeof(frame), NULL, &frame)); 
    verify_noerr(HIViewFindByID(frame, kHIViewWindowContentID, &content)); 
    HIViewInstallEventHandler(content, hsMenuContentEventHandler, GetEventTypeCount(kContentEvents), 
      kContentEvents, 0, NULL); 
    } 
} 

return err; 
} 

К сожалению, я забыл, что немного:

- (MenuRef) carbonMenuRef 
{ 
    MenuRef carbonMenuRef = NULL; 

    if (carbonMenuRef == NULL) { 
     extern MenuRef _NSGetCarbonMenu(NSMenu *); 
     carbonMenuRef = _NSGetCarbonMenu(self); 

     if (carbonMenuRef == NULL) { 
      NSMenu *theMainMenu = [NSApp mainMenu]; 
      NSMenuItem *theDummyMenuItem = [theMainMenu addItemWithTitle: @"sub" action: NULL keyEquivalent: @""]; 

      if (theDummyMenuItem != nil) { 
       [theDummyMenuItem setSubmenu:self]; 
       [theDummyMenuItem setSubmenu:nil]; 
       [theMainMenu removeItem:theDummyMenuItem]; 

       carbonMenuRef = _NSGetCarbonMenu(self); 
      } 
     } 
    } 

    if (carbonMenuRef == NULL) { 
     extern MenuRef _NSGetCarbonMenu2(NSMenu *); 
     carbonMenuRef = _NSGetCarbonMenu2(self); 
    } 

    return carbonMenuRef; 
} 
+0

Код выглядит многообещающим, но я не смог заставить его работать еще. Он генерирует множество ошибок и предупреждений при создании в Xcode для меня, возможно, все это теперь устарело? – alistairholt

+0

Я действительно получил это здание без ошибок после замены [menu carbonMenuRef] на _NSGetCarbonMenu (меню), но это, похоже, не влияет на меню. – alistairholt

+0

Важной линией является «metrics.top = 0;» –