Pergunta

Quero criar um menu para um item de barra de status como o visto no aplicativo PastebotSync da Tapbot:

Alguém tem alguma idéia de como alcançar a área personalizada na parte superior do menu que está nivelada com a parte superior?

Eu tentei/pensei em algumas maneiras em potencial de fazê -lo:

  • Nsmenuitem padrão com vista - não está nivelado com a parte superior do menu
  • Algum código de hack -ish para colocar uma NSWIDOW sobre a área no topo do menu - não é ótimo, pois não desaparece bem com o menu quando fecha
  • Abandonando um nsmenu completamente e usando uma NSView - ainda não tentei isso, mas eu realmente não quero ter que fazer alguns botões falsos ou algo que age como nsmenuitems

Alguém tem idéias ou sugestões melhores?

Obrigado!

Foi útil?

Solução

Caso alguém venha procurar, eu postei uma solução para isso em Visualização personalizada acima do nsmenuitem

Aqui está o código:

@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

Use assim:

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;

Outras dicas

Eu tinha a mesma necessidade nas versões iniciais do Houdahspot 2. Eu o fiz trabalhando com uma limitação: meu código deixa o menu com cantos quadrados na parte inferior.

Desde então, abandonei essa configuração, à medida que o recurso BlitzSearch no Houdahspot cresceu para precisar de uma interface do usuário mais complexa, encontrei outras limitações com o uso de NSViews em um NSMENU.

De qualquer forma, aqui está o código original cuidando desses 3 pixels extras:

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

Desculpe, eu esqueci isso:

- (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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top