2010-10-31 64 views
1

我想創建一個像在Tapbot的PastebotSync應用程序看到一個狀態欄項的菜單:逆向工程的NSMenu一個狀態欄項目

沒有人有任何想法如何實現菜單頂部與頂部齊平的自定義區域?

我試過的做這件事的一些潛在的方法/思想:以期

  • 標準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的早期版本中也有同樣的需求。我確實得到了它的一個限制:我的代碼在底部留下方形角的菜單。

我已經放棄了這個設置,因爲HoudahSpot中的BlitzSearch功能發展到需要更復雜的用戶界面,所以我在NSMenu中使用NSViews遇到了其他限制。

無論如何,這裏是原代碼服用這些額外的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 2010-11-01 11:31:18

+0

我用_NSGetCarbonMenu(菜單)替換[menu carbonMenuRef]後實際上沒有錯誤,但它似乎沒有影響菜單。 – alistairholt 2010-11-01 11:44:38

+0

重要的一行是「metrics.top = 0;」 – 2010-11-02 06:54:13