如何从其他应用程序获取所选文本?

时间:2009-09-28 13:54:51

标签: objective-c cocoa

我将很快开发一个应用程序,它需要在最前面的应用程序窗口中获取当前选定的文本,无论是Safari,Pages,TextEdit,Word等,并对该文本执行某些操作。

我的目标是找到一个适用于尽可能多的应用程序的解决方案。到目前为止,我考虑过使用 AppleScript ,但这会限制可以与我的服务一起使用的应用程序数量。至少必须支持这些常见的应用程序:Safari,Firefox(没有AppleScript?),Word,Pages,Excel,TextEdit,......

我还想过将剪贴板的内容保存在临时变量中,然后模拟文本复制操作(Cmd-C),获取文本然后将原始内容放回去。这样做当模拟复制操作时,可能会突出显示“编辑”菜单项,对我来说似乎有些笨拙。 IMO这种解决方案对商业产品来说似乎不够好。

我也希望获得的不仅仅是选择(例如:Safari或Word中的页面的完整内容等),以便在将来添加一些额外的功能。

有关如何实施此行为的任何想法/详细信息?

提前感谢任何提示!

N.B:我需要支持至少10.4及以上,但理想情况下也要支持10.4以上。

更新:

我选择的解决方案:使用“责任链”设计模式(GOF)结合3种不同的输入方法(粘贴板,AppleScript和辅助功能),自动使用最佳可用输入源。

请注意,当使用NSAppleScript的executeAndReturnError:方法返回NSAppleEventDescriptor(假设为“描述符”实例)时,对于[descriptor stringValue]方法返回一些内容,在AppleScript中必须使用“return someString”OUTSIDE of“告诉“阻止其他任何东西都不会被退回。

2 个答案:

答案 0 :(得分:1)

辅助功能将起作用,但仅限于辅助设备的访问权限已启用。

您需要获取当前应用程序,然后获取其重点UI元素,然后获取其选定的文本范围及其值(全文)和选定的文本范围。您可以只获取其选定的文本,但这可以连接或忽略多个选择。

准备好任何失败的步骤:应用程序可能没有任何窗口,可能没有焦点的UI元素,焦点的UI元素可能没有文本,并且焦点的UI元素可能只有一个空选定的文字范围。

答案 1 :(得分:0)

如果您不经常需要选定的文本,可以通过编程方式按Command + C,然后从剪贴板中获取所选文本。但在我的测试中,只有在关闭App Sandbox(无法提交到Mac App Store)时才能使用此功能。

这是Swift 3代码:

     func performGlobalCopyShortcut() {

        func keyEvents(forPressAndReleaseVirtualKey virtualKey: Int) -> [CGEvent] {
            let eventSource = CGEventSource(stateID: .hidSystemState)
            return [
                CGEvent(keyboardEventSource: eventSource, virtualKey: CGKeyCode(virtualKey), keyDown: true)!,
                CGEvent(keyboardEventSource: eventSource, virtualKey: CGKeyCode(virtualKey), keyDown: false)!,
            ]
        }

        let tapLocation = CGEventTapLocation.cghidEventTap
        let events = keyEvents(forPressAndReleaseVirtualKey: kVK_ANSI_C)

        events.forEach {
            $0.flags = .maskCommand
            $0.post(tap: tapLocation)
        }
    }

    performGlobalCopyShortcut()

    DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { // wait 0.05s for copy.
        let clipboardText = NSPasteboard.general().readObjects(forClasses: [NSString.self], options: nil)?.first as? String ?? ""
        print(clipboardText)
    }