2011-04-14 57 views
14

我正在尝试编写一个应用程序,允许用户从Finder中拖动文件并将其放到NSStatusItem上。到目前为止,我创建了一个实现拖放界面的自定义视图。当我将这个视图作为NSWindow的子视图添加时,它全部正常工作 - 鼠标光标提供了适当的反馈,并且在我的代码被删除时执行。使用NSStatusItem拖放

但是,当我使用与NSStatusItem's视图相同的视图时,它的行为不正确。鼠标光标提供了适当的反馈,指出文件可以被删除,但是当我删除文件时,我的drop代码永远不会被执行。

有没有什么特别的我需要做的,以使拖放与NSStatusItem

回答

30

我终于开始测试它,它完美的工作,所以你的代码肯定有问题。

这里有一个自定义视图,允许拖动:

@implementation DragStatusView 

- (id)initWithFrame:(NSRect)frame 
{ 
    self = [super initWithFrame:frame]; 
    if (self) { 
     //register for drags 
     [self registerForDraggedTypes:[NSArray arrayWithObjects: NSFilenamesPboardType, nil]]; 
    } 

    return self; 
} 

- (void)drawRect:(NSRect)dirtyRect 
{ 
    //the status item will just be a yellow rectangle 
    [[NSColor yellowColor] set]; 
    NSRectFill([self bounds]); 
} 

//we want to copy the files 
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender 
{ 
    return NSDragOperationCopy; 
} 

//perform the drag and log the files that are dropped 
- (BOOL)performDragOperation:(id <NSDraggingInfo>)sender 
{ 
    NSPasteboard *pboard; 
    NSDragOperation sourceDragMask; 

    sourceDragMask = [sender draggingSourceOperationMask]; 
    pboard = [sender draggingPasteboard]; 

    if ([[pboard types] containsObject:NSFilenamesPboardType]) { 
     NSArray *files = [pboard propertyListForType:NSFilenamesPboardType]; 

     NSLog(@"Files: %@",files); 
    } 
    return YES; 
} 


@end 

这里是你如何创建的状态项:

NSStatusItem* item = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength] retain]; 

DragStatusView* dragView = [[DragStatusView alloc] initWithFrame:NSMakeRect(0, 0, 24, 24)]; 
[item setView:dragView]; 
[dragView release]; 
+3

太棒了!但我如何处理点击这个视图并显示菜单? – Oleg 2012-06-20 11:14:57

+0

@Oleg是否能够实现点击处理并在此视图上显示菜单? – 2013-02-05 10:10:21

+1

我添加按钮。然后添加DragStatusView作为子视图。 \t'_titleButton = [[NSButton alloc] initWithFrame:NSMakeRect(0,-2,26,24)]; \t [_titleButton setBordered:NO]; \t [_titleButton setButtonType:NSMomentaryChangeButton]; \t [_titleButton setImagePosition:NSImageOnly]; \t [_titleButton setBezelStyle:NSThickerSquareBezelStyle]; \t [_titleButton setTarget:self]; \t \t \t \t [_titleButton setImage:[NSImage imageNamed:@“IconDefault.png”]]; \t \t [_titleButton setAction:@selector(showMenu :)];; \t \t \t self.view = [[ILDragStatusView alloc] initWithFrame:NSMakeRect(0,1,26,24)]; \t [self.view addSubview:_titleButton];' – Oleg 2013-02-06 11:58:48

11

由于优胜美地,对NSStatusItem设置视图的方法已经过时,但好在有使用上NSStatusItemNSStatusItemButton财产好得多方式:

- (void)applicationDidFinishLaunching: (NSNotification *)notification { 
    NSImage *icon = [NSImage imageNamed:@"iconName"]; 
    //This is the only way to be compatible to all ~30 menu styles (e.g. dark mode) available in Yosemite 
    [normalImage setTemplate:YES]; 
    statusItem.button.image = normalImage; 

    // register with an array of types you'd like to accept 
    [statusItem.button.window registerForDraggedTypes:@[NSFilenamesPboardType]]; 
    statusItem.button.window.delegate = self; 

}

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

- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender { 
    //drag handling logic 
} 

请注意,button属性仅可在出发10.10你可能要保留旧的解决方案,如果你支持10.9小牛或以下。

+0

非常感谢。出于某种原因,当我将该文件从扩展坞的“Downloads”堆栈(从Finder中正常工作)拖出时,这不起作用。任何想法为什么这可能会发生? – 2015-05-07 02:14:21

+0

@CoffeeBite我遇到了同样的问题,正如本报告中所报道的那样:http://openradar.appspot.com/radar?id = 1745403。你最终找到了解决这个问题的方法吗? – Pim 2017-12-18 14:48:19

+0

@Pim是的。'performDragOperation'不被调用,但是'draggingEnded'是。所以我检查拖动是否在状态菜单项的框架内结束。 ''' FUNC draggingEnded(发件人:NSDraggingInfo)!{ 如果发件人=零{ 如果NSPointInRect(发件人.draggingLocation(),statusItem.button.frame!){ 如果让纸板:NSPasteboard =发送者! draggingPasteboard(){ //从剪贴板数据获取文件并做些事情。 } } } } ''' – 2017-12-18 20:57:02