简体   繁体   English

NSMenuItem自定义视图上方的差距

[英]Gap above NSMenuItem custom view

I am using the setView: method on an NSMenuItem to set a custom view. 我使用setView:方法上NSMenuItem设置自定义视图。 In this custom view there is an image which takes the whole of the view. 在此自定义视图中,有一个图像占据整个视图。 The NSMenuItem with this custom view is the first in the menu but the problem is it doesn't sit flush with the top of the menu, there is a big gap as you can see here: 具有此自定义视图的NSMenuItem是菜单中的第一个,但问题是它与菜单顶部没有齐平,有一个很大的差距,你可以在这里看到:

替代文字

Why is this happening and how can I stop it? 为什么会这样,我怎么能阻止它呢?


EDIT 编辑

I am using this code now but I am getting EXC_BAD_ACCESS on the line InstallControlEventHandler . 我现在正在使用此代码,但我在InstallControlEventHandler行上获得了EXC_BAD_ACCESS

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

Also note the line metrics.top = 0 this is the line which should remove the gap at the top. 还要注意行metrics.top = 0这是应该删除顶部间隙的行。 However I cannot get it work that far. 但是我无法让它工作到那么远。 Does anyone know why I would be recieving an EXC_BAD_ACCESS there. 有谁知道为什么我会在那里收到EXC_BAD_ACCESS I have already created and allocated statusMenu so surely it should work? 我已经创建并分配了statusMenu所以它肯定应该有效吗?

Your post is tagged "Objective-C" and "Cocoa", although your sample code is C and Carbon. 您的帖子被标记为“Objective-C”和“Cocoa”,尽管您的示例代码是C和Carbon。 I assume you'd prefer a Cocoa solution? 我想你更喜欢Cocoa解决方案?

It's actually pretty simple in Cocoa. 在Cocoa中它实际上非常简单。 The only trick is learning how to draw outside the lines. 唯一的技巧是学习如何在线外画画。 :-) :-)

@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 it like this: 像这样使用它:

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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM