我正在开发一个可以处理图像的 MacOS 应用程序。这个想法是应用程序大部分时间都隐藏起来,但如果您从另一个应用程序或取景器中拖动图像,我的应用程序将显示,您可以将图像拖动到它上面。基本上是一个待命的放置区,以供您需要时使用。
一切工作都很完美,除了我不知道如何只显示某些类型的可拖动项目(URL、fileURL、FilePromises 和图像)的应用程序。我现在所拥有的显示了应用程序的任何类型的拖动,甚至选择页面上的文本或单击并单击并拖动菜单栏。
我尝试查看 NSPasteboard 进行拖动,但似乎在拖动时没有更新。我看过一些关于使用辅助功能来查看鼠标下方的内容的帖子,但这似乎很脆弱,我还不知道如何做到这一点。
这是我用来检测全局拖放的代码:
dragMonitor = NSEvent.addGlobalMonitorForEvents(matching:.leftMouseDragged) { event in
if !self.isDragging {
self.isDragging = true
if let dropzoneViewController = self.dropzoneViewController, dropzoneViewController.shouldShowForDrag(event: event) {
self.show()
}
}
}
upMonitor = NSEvent.addGlobalMonitorForEvents(matching:.leftMouseUp) { event in
if self.isDragging {
self.hide()
self.isDragging = false
}
}
该函数又调用以下函数,该函数应用应用程序的逻辑来确定是否处理拖动。
func shouldShowForDrag(event: NSEvent) -> Bool {
return self.dropTarget.canHandleDrop(NSPasteboard(name: .drag))
}
为了清楚起见,以下是应用程序在应用程序窗口上方处理拖动操作的方式:
override func performDragOperation(_ draggingInfo: NSDraggingInfo) -> Bool {
isReceivingDrag = false
if let dropTarget = dropTarget, dropTarget.canHandleDrop(draggingInfo.draggingPasteboard) {
dropTarget.handleDrop(draggingInfo.draggingPasteboard)
return true
} else {
return false
}
}
这两个检查之间的唯一区别是全局检查 (
shouldShowForDrag(event:)
) 使用 NSPasteboard(name: .drag)
,它在 NSEvent.addGlobalMonitorForEvents(matching:)
触发时不是当前的。可拖动进入我的窗口时的逻辑使用提供的粘贴板 (draggingInfo.draggingPasteboard
),当然,它对于所拖动的内容是准确的。
最后,这是确定接受哪些拖动的基本逻辑:
func canHandleDrop(_ pasteBoard: NSPasteboard) -> Bool {
let urlFilteringOptions = [NSPasteboard.ReadingOptionKey.urlReadingContentsConformToTypes:NSImage.imageTypes]
if let urls = pasteBoard.readObjects(forClasses: [NSURL.self], options:urlFilteringOptions) as? [URL], urls.count > 0 {
return true
} else if let filePromises = pasteBoard.readObjects(forClasses: [NSFilePromiseReceiver.self], options: nil) as? [NSFilePromiseReceiver], filePromises.count > 0 {
return true
} else if let images = pasteBoard.readObjects(forClasses: [NSImage.self], options: [:]) as? [NSImage], images.count > 0 {
return true
}
return false
}
前两条是最重要的。检测 NSImages 并不是严格要求的。
我知道这是可以做到的,因为我正在使用其他应用程序(做类似但不同的事情),并且它们的工作原理与我想要实现的目标完全相同。但到目前为止我还在用头撞墙。
谢谢
您可以简单地检查拖动粘贴板的内容类型
let pasteboard = NSPasteboard(name: .drag)
if let types = pasteboard.types, types.contain(.fileURL) {
if !self.isDragging {
self.isDragging = true
if let dropzoneViewController = self.dropzoneViewController, dropzoneViewController.shouldShowForDrag(event: event) {
self.show()
}
}
}