2010-12-26 7 views
18

Ich verwende die setView: Methode auf eine NSMenuItem, um eine benutzerdefinierte Ansicht festzulegen. In dieser benutzerdefinierten Ansicht befindet sich ein Bild, das die gesamte Ansicht erfasst. Die NSMenuItem mit dieser benutzerdefinierten Ansicht der ersten im Menü ist aber das Problem ist es nicht mit dem oberen Rande des Menüs bündig nicht sitzt, gibt es eine große Lücke, wie Sie hier sehen können:Gap über NSMenuItem benutzerdefinierte Ansicht

alt text

Warum passiert das und wie kann ich es stoppen?


EDIT

ich diesen Code jetzt bin mit aber ich bin immer EXC_BAD_ACCESS auf der Linie 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; 
} 

beachten Sie auch die Linie metrics.top = 0 das ist die Linie, die die Lücke an der Spitze entfernen sollte. Aber ich kann es nicht so weit bringen. Weiß jemand, warum ich dort eine EXC_BAD_ACCESS erhalten würde. Ich habe bereits statusMenu erstellt und zugewiesen, also sollte es sicher funktionieren?

+0

Es sieht aus wie ein weißer Abstandshalter an der Ober- und Unterseite jeden Menüs ist. Ich würde auch gerne wissen, ob es möglich ist, es zu vermeiden. –

+0

Ich nehme an, der schwarze Teil ist das Bild, nicht die Lücke? Zwischen den oberen und unteren Bereichen des Menüs gibt es zusätzlich zu den Separator-Elementen eine Füllung, die aus ästhetischen Gründen besteht. Ich bin mir nicht sicher, ob dies getan wird, ist NSMenu oder NSMenuItem, aber Sie müssen möglicherweise die eine oder andere Unterklasse, um es zu verhindern. – d11wtq

+0

Ich habe etwas recherchiert und diese http://www.mail-archive.com/[email protected]/msg26997.html aufgedeckt. Es sieht so aus, als würde ein benutzerdefiniertes NSMenu benötigt werden und ein paar private API-Basteleien . –

Antwort

15

Ihr Beitrag ist mit "Objective-C" und "Cocoa" gekennzeichnet, obwohl Ihr Beispielcode C und Carbon ist. Ich nehme an, Sie würden eine Cocoa-Lösung bevorzugen?

Es ist eigentlich ziemlich einfach in Cocoa. Der einzige Trick ist, zu lernen, wie man außerhalb der Linien zeichnet. :-)

@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 

es wie folgt verwendet:

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

Funktioniert hervorragend! Habe gerade einen Tippfehler in deinem Code gefunden, obwohl du 'initWithRect:' gesagt hast, wenn es 'initWithFrame:' ​​sein sollte. Vielen Dank, ich würde es nie so einfach machen! – Joshua

+0

Ah danke, repariere den Tippfehler. Froh, dass es dein Problem gelöst hat! – skue

+0

joshua: Wenn der obige Code weiterhin benötigt wird, ohne dass EXC_BAD_ACCESS funktioniert, überprüfen Sie bitte http: // stackoverflow.com/questions/6633843/how-to-remove-nsmenuitem-gap-über-custom-view-solved – AmitSri