如何使用 NSStatusItem 作为拖动目的地?
Posted
技术标签:
【中文标题】如何使用 NSStatusItem 作为拖动目的地?【英文标题】:How to use a NSStatusItem as a drag destination? 【发布时间】:2011-08-25 17:17:37 【问题描述】:我正在尝试构建一个允许用户将文件从 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];
还是什么都没有。那我哪里做错了?
谢谢!
【问题讨论】:
你实现了 draggingEntered: 和 performDragOperation: 方法吗? 是的,我有。我会更新我的问题以包括它们。 我怀疑你只是无法做到这一点。将对象拖动到菜单不是正常的 UI 行为,我认为NSStatusItem
视图可以具有的交互可能存在系统级限制。如果视图响应的不是 mouseUp/Down,我会感到惊讶。
@Rob,这很有趣。那么,CloudApp 之类的应用程序如何让您将文件拖放到状态栏图标上?
@Wevah,你能回答这个问题吗?
【参考方案1】:
通过反复试验,我偶然发现了解决方案。我在 awakeFromNib 消息中注册了可接受的拖动类型(如原始问题所示)。但是,我没有使用 IB 来设置此视图,因此从未调用过此方法。将注册码移至 initFromFrame 消息似乎可以解决问题。
- (id)initWithFrame:(NSRect)frame
self = [super initWithFrame:frame];
if (self)
...
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
return self;
【讨论】:
哎呀,我在编辑我的之前没有阅读这个自我答案。你应该接受你的正确的! (投票赞成。)【参考方案2】:编辑:哦,您在-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
在我的自定义视图的实现中。这可确保菜单行为与默认行为相同。
【讨论】:
我将 NSMenu 设置为我的自定义视图,而不是 NSStatusItem。更重要的是,您如何处理拖动目的地? 哦,哎呀。我会更新我的答案。不过,目前睡眠不足……以上是关于如何使用 NSStatusItem 作为拖动目的地?的主要内容,如果未能解决你的问题,请参考以下文章
使用React Native的MapView,我如何确定何时到达最终拖动目的地?
在 NSStatusItem 中使用 NSProgressIndicator