objective-c cocoa macos nsmenu nsmenuitem

objective c - Gap sobre la vista personalizada de NSMenuItem



objective-c cocoa (1)

Su publicación está etiquetada como "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

Úselo así:

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;

Estoy usando 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 encuentra alineado con la parte superior del menú, hay una gran brecha como se puede ver aquí:

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

EDITAR

Estoy usando este código ahora, pero estoy obteniendo 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 metrics.top = 0 esta es la línea que debería eliminar el espacio en la parte superior. Sin embargo, no puedo hacer que funcione tan lejos. ¿Alguien sabe por qué recibiría un EXC_BAD_ACCESS allí? Ya he creado y asignado statusMenu así que seguramente debería funcionar.