2010-12-26 47 views
18

Tôi đang sử dụng phương pháp setView: trên NSMenuItem để đặt chế độ xem tùy chỉnh. Trong chế độ xem tùy chỉnh này, có một hình ảnh chụp toàn bộ khung nhìn. Các NSMenuItem với giao diện tùy chỉnh này là lần đầu tiên trong menu nhưng vấn đề là nó không ngồi ngang bằng với đỉnh của menu, có một khoảng cách lớn như bạn có thể xem tại đây:Khoảng cách phía trên chế độ xem tùy chỉnh NSMenuItem

alt text

Tại sao điều này có xảy ra không và làm thế nào tôi có thể ngăn chặn nó?


EDIT

Tôi đang sử dụng mã này, nhưng bây giờ tôi nhận được EXC_BAD_ACCESS trên dòng 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; 
} 

Cũng lưu ý dòng metrics.top = 0 đây là dòng nên loại bỏ khoảng trống ở trên cùng. Tuy nhiên tôi không thể làm cho nó hoạt động xa đến thế. Có ai biết tại sao tôi sẽ nhận được một EXC_BAD_ACCESS ở đó. Tôi đã tạo và phân bổ statusMenu vì vậy chắc chắn nó sẽ hoạt động?

+0

Dường như có một spacer trắng ở đầu và cuối mỗi menu. Tôi cũng muốn biết nếu nó có thể tránh được nó. –

+0

Tôi cho rằng phần màu đen là hình ảnh chứ không phải khoảng cách? Có một số phần đệm giữa đầu và cuối trình đơn, ngoài các mục phân cách, vì lý do thẩm mỹ. Tôi không chắc chắn nếu điều này được thực hiện là NSMenu hoặc NSMenuItem, nhưng bạn có thể cần phải phân lớp hoặc một hoặc khác để ngăn chặn nó. – d11wtq

+0

Tôi đã thực hiện một số nghiên cứu và đã bật http://www.mail-archive.com/[email protected]/msg26997.html Dường như NSMenu tùy chỉnh sẽ là cần thiết và một số tin nhắn API riêng tư . –

Trả lời

15

Bài đăng của bạn được gắn thẻ "Objective-C" và "Cocoa", mặc dù mã mẫu của bạn là C và Carbon. Tôi cho rằng bạn thích một giải pháp Cocoa?

Nó thực sự khá đơn giản trong Cocoa. Bí quyết duy nhất là học cách vẽ ra ngoài đường kẻ. :-)

@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 

Sử dụng nó như thế này:

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

Hoạt động tuyệt vời! Chỉ tìm thấy lỗi đánh máy trong mã của bạn mặc dù bạn đã nói 'initWithRect:' khi nó phải là 'initWithFrame:'. Cảm ơn rất nhiều, tôi không bao giờ mặc dù nó sẽ dễ dàng như thế này! – Joshua

+0

Ah cảm ơn, đã sửa lỗi đánh máy. Vui mừng nó giải quyết prob của bạn! – skue

+0

joshua: nếu vẫn cần mã ở trên để hoạt động mà không có EXC_BAD_ACCESS, vui lòng kiểm tra bài đăng http: // stackoverflow.com/questions/6633843/how-to-remove-nsmenuitem-gap-above-custom-view-giải quyết – AmitSri

Các vấn đề liên quan