为什么不将内部拖动到我的 Cocoa 应用程序工作?
Why don't drags internal to my Cocoa application work?
我的 Cocoa 应用程序的工作方式是每个 window 有一个子类 NSView 并在其中呈现许多内部视图。我最近开始使用 NSView 的 beginDraggingSessionWithItems:event:source 功能来支持将文件承诺拖到外部应用程序(如 Finder)。但是内部拖动类型(基本类型 String 和 Binary blob)需要从 NSWindow 的 dragImage 移植过来。我注意到的主要区别是 beginDraggingSessionWithItems 默认情况下不允许我从我的应用程序拖动到我的应用程序......就像在其内部一样。例如,如果我有一个树控件并使用 DnD 在它周围移动元素是行不通的。将文件拖到应用程序中有效。将 promises 拖出应用程序是可行的。内部什么都没有。
一些代码。这是我创建二进制项的地方:
auto drag_items = [[NSMutableArray alloc] init];
auto item = [[NSPasteboardItem alloc] init];
NSData *data = [NSData dataWithBytes:myBinary.Data length:myBinary.Length];
[item setData:data forType:dd.Format.NsStr()];
auto drag_item = [[NSDraggingItem alloc] initWithPasteboardWriter:item];
drag_item.draggingFrame = NSMakeRect(floor(position.x), floor(position.y), 32, 32);
[drag_items addObject:drag_item];
然后开始拖动:
NSDraggingSession *session = [myNsWindow.contentView beginDraggingSessionWithItems:drag_items
event:myEvent
source:DragSrc];
拖拽源是这样实现draggingSession的:
- (NSDragOperation)draggingSession:(nonnull NSDraggingSession *)session
sourceOperationMaskForDraggingContext:(NSDraggingContext)context
{
switch (context)
{
case NSDraggingContextOutsideApplication:
return NSDragOperationCopy;
case NSDraggingContextWithinApplication:
return NSDragOperationCopy | NSDragOperationGeneric | NSDragOperationMove;
default:
return NSDragOperationNone;
}
}
完整的拖动源代码在 GDragAndDrop.mm, and the full drag target code is available in LCocoaView.mm 中可用。
我看到 none 的拖动目标方法被调用,当我释放鼠标时,图像会快速回到拖动源。
我记得有一个标志或其他设置允许同一个视图既是源视图又是目标视图。但是我这辈子都找不到。
编辑:这些是我传递给 NSView 的 registerForDraggedTypes 的类型:
"public.item"
"com.apple.NSFilePromiseItemMetaData"
"dyn.ah62d4rv4gu8yc6durvwwa3xmrvw1gkdusm1044pxqyuha2pxsvw0e55bsmwca7d3sbwu"
"com.apple.pasteboard.promised-file-content-type"
我认为发生的事情是注册的类型与我尝试拖动的不匹配。我想要的是一个通配符,以便接收者获得所有类型,而我在较低层进行过滤。这就是为什么列表中有 'public.item',但它没有按我的预期工作。
所以问题是视图没有为我拖动的类型注册。我认为 'public.item' 将适用于不同的类型,所以我拖什么并不重要。但这只有在您拖动的类型符合 'public.item' 时才有效,而在我的情况下,我没有为该拖动类型导出 UTI。所以我的拖动类型和'public.item'之间没有link。
我是这样定义 UTI 的:
一旦我这样做了,我就可以在我的应用程序中拖动节点。
我的 Cocoa 应用程序的工作方式是每个 window 有一个子类 NSView 并在其中呈现许多内部视图。我最近开始使用 NSView 的 beginDraggingSessionWithItems:event:source 功能来支持将文件承诺拖到外部应用程序(如 Finder)。但是内部拖动类型(基本类型 String 和 Binary blob)需要从 NSWindow 的 dragImage 移植过来。我注意到的主要区别是 beginDraggingSessionWithItems 默认情况下不允许我从我的应用程序拖动到我的应用程序......就像在其内部一样。例如,如果我有一个树控件并使用 DnD 在它周围移动元素是行不通的。将文件拖到应用程序中有效。将 promises 拖出应用程序是可行的。内部什么都没有。
一些代码。这是我创建二进制项的地方:
auto drag_items = [[NSMutableArray alloc] init];
auto item = [[NSPasteboardItem alloc] init];
NSData *data = [NSData dataWithBytes:myBinary.Data length:myBinary.Length];
[item setData:data forType:dd.Format.NsStr()];
auto drag_item = [[NSDraggingItem alloc] initWithPasteboardWriter:item];
drag_item.draggingFrame = NSMakeRect(floor(position.x), floor(position.y), 32, 32);
[drag_items addObject:drag_item];
然后开始拖动:
NSDraggingSession *session = [myNsWindow.contentView beginDraggingSessionWithItems:drag_items
event:myEvent
source:DragSrc];
拖拽源是这样实现draggingSession的:
- (NSDragOperation)draggingSession:(nonnull NSDraggingSession *)session
sourceOperationMaskForDraggingContext:(NSDraggingContext)context
{
switch (context)
{
case NSDraggingContextOutsideApplication:
return NSDragOperationCopy;
case NSDraggingContextWithinApplication:
return NSDragOperationCopy | NSDragOperationGeneric | NSDragOperationMove;
default:
return NSDragOperationNone;
}
}
完整的拖动源代码在 GDragAndDrop.mm, and the full drag target code is available in LCocoaView.mm 中可用。
我看到 none 的拖动目标方法被调用,当我释放鼠标时,图像会快速回到拖动源。
我记得有一个标志或其他设置允许同一个视图既是源视图又是目标视图。但是我这辈子都找不到。
编辑:这些是我传递给 NSView 的 registerForDraggedTypes 的类型:
"public.item"
"com.apple.NSFilePromiseItemMetaData"
"dyn.ah62d4rv4gu8yc6durvwwa3xmrvw1gkdusm1044pxqyuha2pxsvw0e55bsmwca7d3sbwu"
"com.apple.pasteboard.promised-file-content-type"
我认为发生的事情是注册的类型与我尝试拖动的不匹配。我想要的是一个通配符,以便接收者获得所有类型,而我在较低层进行过滤。这就是为什么列表中有 'public.item',但它没有按我的预期工作。
所以问题是视图没有为我拖动的类型注册。我认为 'public.item' 将适用于不同的类型,所以我拖什么并不重要。但这只有在您拖动的类型符合 'public.item' 时才有效,而在我的情况下,我没有为该拖动类型导出 UTI。所以我的拖动类型和'public.item'之间没有link。
我是这样定义 UTI 的:
一旦我这样做了,我就可以在我的应用程序中拖动节点。