首页 文章

为状态栏项反向设计NSMenu

提问于
浏览
1

我想为状态栏项目创建一个菜单,如Tapbot的PastebotSync应用程序中所示:

有没有人有任何想法如何实现菜单顶部的自定义区域与顶部齐平?

我已经尝试过/想过几种可行的方法:

  • 带有视图的标准NSMenuItem - 不与菜单顶部齐平

  • 一些hack-ish代码将NSWindow放在菜单顶部的区域 - 不是很好,因为当它关闭时菜单不会很好地淡出

  • 完全放弃NSMenu并使用NSView - 避免't tried this yet but I don' t真的想制作一些虚假按钮或充当NSMenuItems的东西

有没有更好的想法或建议?

Thanks!

2 回答

  • 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;
    }
    

相关问题