【发布时间】:2011-05-30 20:21:09
【问题描述】:
我在NSMenuItem 上使用setView: 方法来设置自定义视图。在这个自定义视图中,有一个图像占据了整个视图。带有此自定义视图的NSMenuItem 是菜单中的第一个,但问题是它与菜单顶部不齐,您可以在此处看到一个很大的差距:
为什么会发生这种情况,我该如何阻止它?
编辑
我现在正在使用此代码,但我在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;
}
还要注意metrics.top = 0 行,这是应该消除顶部间隙的行。但是我不能让它工作那么远。有谁知道我为什么会在那里收到EXC_BAD_ACCESS。我已经创建并分配了statusMenu,所以它应该可以工作吗?
【问题讨论】:
-
看起来每个菜单的顶部和底部都有一个空格。我也想知道是否可以避免。
-
我假设黑色部分是图像,而不是间隙?出于美学原因,除了分隔项之间,菜单的顶部和底部之间还有一些填充。我不确定这样做是 NSMenu 还是 NSMenuItem,但您可能需要将其中一个子类化以防止它发生。
-
我做了一些研究,发现了这个 mail-archive.com/cocoa-dev@lists.apple.com/msg26997.html 看起来需要一个自定义的 NSMenu 和一些私有 API 修补。
-
这很有趣,但是您如何将最高指标设置为零,我想知道代码会是什么样子,因为我假设它是 Carbon。
-
Joshua :我通过将“InstallControlEventHandler”函数调用替换为“HIViewInstallEventHandler”来使上述代码工作。让我知道是否有帮助。
标签: objective-c cocoa macos nsmenu nsmenuitem