2010-12-26 7 views
18

Estoy utilizando el método setView: en un NSMenuItem para establecer una vista personalizada. En esta vista personalizada hay una imagen que toma la totalidad de la vista. El NSMenuItem con esta vista personalizada es el primero en el menú, pero el problema es que no se sienta a ras de la parte superior del menú, hay una gran brecha como se puede ver aquí:Gap por encima de la vista personalizada de NSMenuItem

alt text

Por qué ¿Está sucediendo esto y cómo puedo detenerlo?


EDITAR

estoy usando el código, pero ahora me estoy haciendo EXC_BAD_ACCESS en la línea InstallControlEventHandler.

-(void)applicationDidFinishLaunching:(NSNotification *)aNotification { 
    HIViewRef contentView; 
    MenuRef menuRef = [statusMenu carbonMenuRef]; 

    HIMenuGetContentView(menuRef, kThemeMenuTypePullDown, &contentView); 

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

    InstallControlEventHandler(contentView, 
          NewEventHandlerUPP((EventHandlerProcPtr)hsMenuCreationEventHandler), 
          GetEventTypeCount(hsEventSpec), 
          hsEventSpec, 
          NULL, 
          NULL); // Get EXC_BAD_ACCESS here. 
} 

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)); 
      InstallControlEventHandler(content, hsMenuContentEventHandler, GetEventTypeCount(kContentEvents), 
             kContentEvents, 0, NULL); 
     } 
    } 

    return err; 
} 

También tenga en cuenta la línea de metrics.top = 0 esta es la línea que debe eliminar la brecha en la parte superior. Sin embargo, no puedo hacer que funcione tan lejos. ¿Alguien sabe por qué estaría recibiendo un EXC_BAD_ACCESS allí. Ya he creado y asignado statusMenu así que seguramente debería funcionar?

+0

Parece que hay un espaciador blanco en la parte superior e inferior de cada menú. También me gustaría saber si es posible evitarlo. –

+0

Supongo que la parte negra es la imagen, no el espacio? Hay algo de relleno entre la parte superior e inferior del menú, además de entre los elementos separadores, por razones estéticas. No estoy seguro de si esto se hace es NSMenu o NSMenuItem, pero es posible que necesite subclase uno o el otro para evitarlo. – d11wtq

+0

Investigué un poco y encontré este http://www.mail-archive.com/[email protected]/msg26997.html Parece que se necesitaría un NSMenu personalizado y algunas modificaciones de API privadas . –

Respuesta

15

Su publicación está etiquetada "Objective-C" y "Cocoa", aunque su código de muestra es C y Carbono. Supongo que preferiría una solución Cocoa?

En realidad, es bastante simple en Cocoa. El único truco es aprender a dibujar fuera de las líneas. :-)

@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 

utilizar de esta manera:

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; 
+0

¡Funciona magníficamente! Acabo de encontrar un error tipográfico en tu código aunque dijiste 'initWithRect:' cuando debería ser 'initWithFrame:'. Muchas gracias, ¡nunca pensé que sería tan fácil como esto! – Joshua

+0

Ah gracias, corrigió el error tipográfico. ¡Me alegro de que haya resuelto tu problema! – skue

+0

joshua: si aún necesita que el código anterior funcione sin EXC_BAD_ACCESS, compruebe la publicación http: // stackoverflow.com/questions/6633843/how-to-remove-nsmenuitem-gap-above-custom-view-resuelto – AmitSri

Cuestiones relacionadas