10

我正在尝试构建一个允许用户将文件从 Finder 拖到菜单栏图标进行处理的应用程序。我在旅途中取得了进步,但我似乎无法登上这座小山。我尝试继承 NSView 并实现拖动消息。

@interface CMDroppableView : NSView <NSMenuDelegate>

我不仅想接受拖动操作,还想在用户单击图标时提供 NSMenu 。我已经设法让 NSMenu 正确显示,但拖动功能仍然难以捉摸。

我的理解是我需要注册我在这里所做的接受的拖动类型:

-(void)awakeFromNib{
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
}

拖动消息:

-(NSDragOperation)draggingEntered:(id <NSDraggingInfo>)sender{
    NSLog(@"Drag Enter");
    return NSDragOperationCopy;
}

-(NSDragOperation)draggingUpdated:(id <NSDraggingInfo>)sender{
    return NSDragOperationCopy;
}

-(void)draggingExited:(id <NSDraggingInfo>)sender{
    NSLog(@"Drag Exit");
}

-(BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender{
     return YES;
}

-(BOOL)performDragOperation:(id <NSDraggingInfo>)sender{
    return YES;
}

这是设置自定义视图的代码:

statusItemView = [[CMDroppableView alloc] init];
[statusItemView retain];
[statusItemView setMenu: statusMenu];

[statusItem setView: statusItemView];   

依然没有。那么我哪里出错了?

谢谢!

4

2 回答 2

7

通过反复试验,我偶然发现了解决方案。我在 awakeFromNib 消息中注册了可接受的拖动类型(如原始问题所示)。但是,我没有使用 IB 来设置此视图,因此从未调用过此方法。将注册码移动到 initFromFrame 消息似乎可以解决问题。

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        ...
        [self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
    }
    return self;
}
于 2011-05-15T17:21:19.703 回答
6

编辑:D'oh,您正在注册拖动类型-awakeFromNib,如果视图没有从笔尖加载,则不会调用。尝试注册您的拖动类型-initWithFrame:

老答案:

IIRC,您无需在状态项上设置菜单。我所做的是让我的自定义视图管理一个菜单,并执行以下操作:

- (void)setMenu:(NSMenu *)menu {
    [menu setDelegate:self];
    [super setMenu:menu];
}

- (void)mouseDown:(NSEvent *)event {
    [statusItem popUpStatusItemMenu:[self menu]]; // or another method that returns a menu
}

- (void)menuWillOpen:(NSMenu *)menu {
    highlight = YES;
    [self setNeedsDisplay:YES];
}

- (void)menuDidClose:(NSMenu *)menu {
    highlight = NO;
    [self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)rect {
    NSImage *img = highlight ? [alternateImage copy] : [image copy];
    NSRect bounds = [self bounds];
    [statusItem drawStatusBarBackgroundInRect:bounds withHighlight:highlight];
    
    // rest of drawing code goes here, including drawing img where appropriate
}

在我的自定义视图的实现中。这可确保菜单行为与默认值相同。

于 2011-05-15T04:41:40.400 回答