2010-12-26 25 views
18

Sto utilizzando il metodo setView: su un NSMenuItem per impostare una visualizzazione personalizzata. In questa vista personalizzata c'è un'immagine che prende tutta la vista. Il NSMenuItem con questa visione personalizzata è il primo nel menu, ma il problema è che non si siede a filo con la parte superiore del menu, c'è un grande divario, come potete vedere qui:Gap sopra NSMenuItem visualizzazione personalizzata

alt text

Perché sta succedendo e come posso fermarlo?


EDIT

Sto usando questo codice, ma ora sto ottenendo EXC_BAD_ACCESS sulla linea 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; 
} 

noti inoltre la linea metrics.top = 0 questa è la linea che deve rimuovere il vuoto in alto. Tuttavia non riesco a farlo funzionare così lontano. Qualcuno sa perché dovrei ricevere uno EXC_BAD_ACCESS lì. Ho già creato e assegnato statusMenu quindi sicuramente dovrebbe funzionare?

+0

Sembra che ci sia un distanziatore bianco nella parte superiore e inferiore di ogni menù. Mi piacerebbe anche sapere se è possibile evitarlo. –

+0

Immagino che la parte nera sia l'immagine, non il divario? C'è una spaziatura tra la parte superiore e inferiore del menu, oltre che tra gli elementi separatori, per ragioni estetiche. Non sono sicuro che se ciò sia fatto è NSMenu o NSMenuItem, ma potrebbe essere necessario sottoclasse l'una o l'altra per impedirlo. – d11wtq

+0

Ho fatto qualche ricerca e alzato questa http://www.mail-archive.com/[email protected]/msg26997.html Sembra un personalizzato NSMenu sarebbe necessario e alcuni ritocchi API private . –

risposta

15

Il post viene contrassegnato "Objective-C" e "Cocoa", sebbene il codice di esempio sia C e Carbon. Immagino che preferiresti una soluzione di cacao?

In realtà è piuttosto semplice in Cocoa. L'unico trucco è imparare a disegnare al di fuori delle linee. :-)

@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 

usare in questo modo:

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

Funziona superbamente! Hai appena trovato un errore nel tuo codice anche se hai detto "initWithRect:" quando dovrebbe essere "initWithFrame:". Grazie mille, non avrei mai pensato che sarebbe stato così facile! – Joshua

+0

Ah grazie, corretto l'errore di battitura. Sono contento che abbia risolto il tuo problema! – skue

+0

Joshua: se ancora necessario il codice qui sopra per lavorare senza EXC_BAD_ACCESS, controllare posta http: // StackOverflow.it/questions/6633843/how-to-remove-nsmenuitem-gap-above-custom-view-risolto – AmitSri

Problemi correlati