我正在尝试构建一个应用程序,允许用户将文件从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];
仍然没有。那么我哪里出错了?
谢谢!
答案 0 :(得分:7)
通过反复试验,我偶然发现了解决方案。我在awakeFromNib消息中注册了可接受的拖动类型(如原始问题中所示)。但是,我没有使用IB来设置此视图,因此从未调用此方法。将注册码移动到initFromFrame消息似乎可以解决问题。
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
...
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
}
return self;
}
答案 1 :(得分:6)
编辑:D'哦,你正在注册-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
}
在我的自定义视图的实现中。这可确保菜单行为与默认行为相同。