【问题标题】:How to use a NSStatusItem as a drag destination?如何使用 NSStatusItem 作为拖动目的地?
【发布时间】: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,你能回答这个问题吗?

标签: objective-c macos cocoa drag-and-drop nsdragginginfo


【解决方案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。更重要的是,您如何处理拖动目的地?
  • 哦,哎呀。我会更新我的答案。不过,目前睡眠不足……
猜你喜欢
  • 2011-08-05
  • 1970-01-01
  • 1970-01-01
  • 2021-07-05
  • 2012-06-13
  • 1970-01-01
  • 2013-04-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多