cocoa - 在 MonoMac NSView 中接收拖放?

标签 cocoa drag-and-drop nsview monomac

这是我在这个问候网站上的第一篇文章。 我是一位经验丰富的 C#、.Net 和 Mono 用户,但在 MonoMac 上却是菜鸟, 我正在尝试编写一个应用程序,该应用程序接收 NSView 上的文件夹并使用其路径来处理文件夹内的文件...

MonoMac 框架没有实现draggingEntered:、draggingUpdated:、draggingExited:、prepareForDragOperation:、performDragOperation:、conclusionDragOperation: 和draggingEnded:

所以我尝试自己实现它们:

[Register("TargetView")] 
public class TargetView:NSView
{
    private static IntPtr selDraggingEntered = Selector.GetHandle ("draggingEntered:");

    private static IntPtr selDraggingUpdated = Selector.GetHandle ("draggingUpdated:");

    private static IntPtr selDraggingExited = Selector.GetHandle ("draggingExited:");

    private static IntPtr selPrepareForDragOperation = Selector.GetHandle ("prepareForDragOperation:");

    private static IntPtr selPerformDragOperation = Selector.GetHandle ("performDragOperation:");

    private static IntPtr selConcludeDragOperation = Selector.GetHandle ("concludeDragOperation:");

    private static IntPtr selDraggingEnded = Selector.GetHandle ("draggingEnded:");

    public TargetView():base(){
    }

    public TargetView(NSCoder coder):base(coder){
    }

    public TargetView(NSObjectFlag t):base(t){
    }

    public TargetView(IntPtr handle):base(handle){
    }

    public TargetView(RectangleF frameRect):base(frameRect){
    }

    [Export ("draggingEntered:")]
    public virtual NSDragOperation DraggingEntered (NSDraggingInfo sender)
    {
        if (sender == null)
        {
            throw new ArgumentNullException ("sender");
        }
        if (this.IsDirectBinding)
        {
            return (NSDragOperation)Messaging.int_objc_msgSend_int (base.Handle, TargetView.selDraggingEntered, (int)sender.DraggingSourceOperationMask);
        }
        return (NSDragOperation)Messaging.int_objc_msgSendSuper_int (base.Handle, TargetView.selDraggingEntered, (int)sender.DraggingSourceOperationMask);
    }

    [Export ("draggingUpdated:")]
    public virtual NSDragOperation DraggingUpdated (NSDraggingInfo sender)
    {
        if (sender == null)
        {
            throw new ArgumentNullException ("sender");
        }
        if (this.IsDirectBinding)
        {
            return (NSDragOperation)Messaging.int_objc_msgSend_int (base.Handle, TargetView.selDraggingUpdated, (int)sender.DraggingSourceOperationMask);
        }
        return (NSDragOperation)Messaging.int_objc_msgSendSuper_int (base.Handle, TargetView.selDraggingUpdated, (int)sender.DraggingSourceOperationMask);
    }

    [Export ("draggingExited:")]
    public virtual void DraggingExited (NSDraggingInfo sender)
    {
        if (sender == null)
        {
            throw new ArgumentNullException ("sender");
        }
        if (this.IsDirectBinding)
        {
            Messaging.void_objc_msgSend_int (base.Handle, TargetView.selDraggingExited, (int)sender.DraggingSourceOperationMask);
        }
        Messaging.void_objc_msgSendSuper_int (base.Handle, TargetView.selDraggingExited, (int)sender.DraggingSourceOperationMask);
    }

    [Export ("prepareForDragOperation:")]
    public virtual bool PrepareForDragOperation (NSDraggingInfo sender)
    {
        if (sender == null)
        {
            throw new ArgumentNullException ("sender");
        }
        if (this.IsDirectBinding)
        {
            return Messaging.bool_objc_msgSend_int (base.Handle, TargetView.selPrepareForDragOperation, (int)sender.DraggingSourceOperationMask);
        }
        return Messaging.bool_objc_msgSendSuper_int (base.Handle, TargetView.selPrepareForDragOperation, (int)sender.DraggingSourceOperationMask);
    }

    [Export ("performDragOperation:")]
    public virtual bool PerformDragOperation (NSDraggingInfo sender)
    {
        if (sender == null)
        {
            throw new ArgumentNullException ("sender");
        }
        if (this.IsDirectBinding)
        {
            return Messaging.bool_objc_msgSend_int (base.Handle, TargetView.selPerformDragOperation, (int)sender.DraggingSourceOperationMask);
        }
        return Messaging.bool_objc_msgSendSuper_int (base.Handle, TargetView.selPerformDragOperation, (int)sender.DraggingSourceOperationMask);
    }

    [Export ("concludeDragOperation:")]
    public virtual void ConcludeDragOperation (NSDraggingInfo sender)
    {
        if (sender == null)
        {
            throw new ArgumentNullException ("sender");
        }
        if (this.IsDirectBinding)
        {
            Messaging.void_objc_msgSend_int (base.Handle, TargetView.selConcludeDragOperation, (int)sender.DraggingSourceOperationMask);
        }
        Messaging.void_objc_msgSendSuper_int (base.Handle, TargetView.selConcludeDragOperation, (int)sender.DraggingSourceOperationMask);
    }

    [Export ("draggingEnded:")]
    public virtual void DraggingEnded (NSDraggingInfo sender)
    {
        if (sender == null)
        {
            throw new ArgumentNullException ("sender");
        }
        if (this.IsDirectBinding)
        {
            Messaging.void_objc_msgSend_int (base.Handle, TargetView.selDraggingEnded, (int)sender.DraggingSourceOperationMask);
        }
        Messaging.void_objc_msgSendSuper_int (base.Handle, TargetView.selDraggingEnded, (int)sender.DraggingSourceOperationMask);
    }
}

但是这些方法没有被调用!

我也尝试RegisterForDraggedTypes,但我不知道将什么作为类型传递给字符串数组!

请帮我解决一下。我已经在谷歌上搜索了 48!

最佳答案

通过进行一些测试并将其与拖放 session 中的 Apple 文档进行比较,我终于找到了问题的答案。

这是我使用的来源,它的世界就像一个魅力:

[Register("DropTargetView")]
public class DropTargetView:NSView
{
    public DropTargetView(IntPtr handle):base(handle){

        RegisterForDraggedTypes(new string[]{"NSFilenamesPboardType"});
    }

    [Export ("draggingEntered:")]
    public NSDragOperation DraggingEntered (NSDraggingInfo sender)
    {
        NSPasteboard pasteboard = sender.DraggingPasteboard;

        bool typeExists = (Array.IndexOf(pasteboard.Types,"NSFilenamesPboardType") >= 0);

        if(typeExists)
        {
            return NSDragOperation.Link;
        }
        else
        {
            return NSDragOperation.None;
        }
    }

    [Export ("performDragOperation:")]
    public bool PerformDragOperation (NSDraggingInfo sender)
    {
        NSPasteboard pasteboard = sender.DraggingPasteboard;

        bool typeExists = (Array.IndexOf(pasteboard.Types,"NSFilenamesPboardType") >= 0);

        if(typeExists)
        {
            NSPasteboardItem[] pasteboardItems = pasteboard.PasteboardItems;

            for(int i = 0; i < pasteboardItems.Length; i++)
            {
                string urlStr = pasteboardItems[i].GetStringForType("public.file-url");

                NSUrl url = new NSUrl (urlStr);

                string filePath = url.Path;

                Console.WriteLine(filePath);
            }

            return true;
        }
        else
        {
            return false;
        }
    }
}

这里有一点解释:

我首先发现 Custom 类是使用 Handle 实例化的,因此我需要在该方法中注册 RegisterForDraggedTypes。 然后,我使用 Apple 文档的示例来跟踪 RegisterForDraggedTypes 字符串常量,并从中取出“RegisterForDraggedTypes”,将其用作文件路径的注册值。 使用Apple的文档示例发现,需要导出的唯一2个方法是draggingEntered:和performDragOperation:,所以我只是导出它们并自己返回预期值,而不是向Cocoa发送消息以返回值,现在一切正常。 从 NSPasteboardItems 中提取文件 URL 所需的 UTI 是 Apple 定义为“public.file-url”的 UTI,因此我用它来获取以下形式的路径:

file://localhost/PathToFileOrFolder/FileOrFolderName[/ if it is a folder]

希望对其他人有帮助。

更新(2015-09-30):

我已将 @M_K 提到的更改应用到我的代码中。

关于cocoa - 在 MonoMac NSView 中接收拖放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9676380/

相关文章:

xcode - 编写 Bridge 和 Apple Mail 脚本

javascript - Gridstack:将小部件从一个网格拖到另一个嵌套的网格中

swift - NSCollectionView 自定义布局启用滚动

javascript - Safari 上的 setDragImage 意外崩溃

ios - 如何在 React Native 中创建拖放操作?

cocoa - 在 Cocoa 应用程序中拖放期间未调用 NSView keyDown

objective-c - NSView 覆盖将鼠标事件传递给底层 subview ?

macos - 如何设置 NSTableView 中显示为行的 View 的宽度?

cocoa - 使用多个 WebView 进行打印

swift - 关闭 NSWindow 后 WKWebView 不回收