2009-09-28 9 views
4

Je vais bientôt travailler sur une application qui doit obtenir le texte actuellement sélectionné dans la fenêtre de l'application la plus en avant, que ce soit Safari, Pages, TextEdit, Word, etc., et faire quelque chose avec ce texte.Comment obtenir le texte sélectionné à partir d'une autre application?

Mon but est de trouver une solution qui fonctionne avec autant d'applications que possible. Jusqu'à présent, j'ai pensé à utiliser AppleScript, mais cela limiterait la quantité d'applications qui pourraient être utilisées avec mon service. Au moins ces applications courantes doivent être supportées: Safari, Firefox (pas AppleScript?), Word, Pages, Excel, TextEdit, ...

J'ai aussi pensé à garder le contenu du presse-papiers dans une variable temporaire puis simuler une opération de copie de texte (Cmd-C), récupérer le texte, puis remettre le contenu original. Cela mettrait probablement en surbrillance l'élément de menu Édition lorsque l'opération de copie est simulée et me semble un peu hachée. IMO cette solution ne semble pas assez bonne pour un produit commercial.

Je cherche également à obtenir plus que la sélection (à savoir: le contenu complet de la page dans Safari ou Word, etc.) pour ajouter quelques fonctionnalités supplémentaires dans le futur.

Des idées/détails sur la façon d'implémenter ce comportement?

Merci d'avance pour tous les conseils! N.B: Je dois prendre en charge au moins 10,4 et plus, mais idéalement plus vieux que 10,4 aussi.

MISE À JOUR:

La solution que j'ai opté pour: Utilisation de la « chaîne de responsabilité » modèle de conception (GOF) pour combiner 3 méthodes différentes (Pasteboard, AppleScript et accessibilité), en utilisant la meilleure source d'entrée disponible automatiquement. Notez que lorsque vous utilisez la méthode executeAndReturnError de NSAppleScript qui retourne un NSAppleEventDescriptor (disons une instance de descripteur), pour que la méthode [descriptor stringValue] renvoie quelque chose, dans votre AppleScript vous devez utiliser "return someString" EXTÉRIEUR d'un "tell" block sinon rien ne sera renvoyé.

+0

Est-il possible que vous pouvez poster un code sur la façon d'obtenir le texte sélectionné dans l'application au premier plan? – Enchilada

Répondre

1

L'accessibilité fonctionnera, mais seulement si l'accès des dispositifs d'assistance est activé.

Vous aurez besoin de l'application en cours, puis de son élément d'interface utilisateur, puis de ses plages de texte sélectionnées et de sa valeur (texte intégral) et des plages de texte sélectionnées. Vous pourriez simplement obtenir le texte sélectionné, mais cela concaténerait ou ignorerait plusieurs sélections. Préparez-vous à l'une de ces étapes pour échouer: L'application ne peut avoir aucune fenêtre, il peut y avoir aucun élément d'interface utilisateur avec focus, l'élément d'interface utilisateur ciblé peut ne pas avoir de texte, et l'élément d'interface utilisateur peut avoir seulement vide la plage de texte sélectionnée.

+0

Les fonctionnalités d'accessibilité semblent intéressantes, mais en utilisant Accessibility Inspector (du Dev.Tools) dans Firefox et Word ne donne aucune valeur intéressante, bien qu'il y ait beaucoup d'informations quand on l'utilise dans Safari. Cela signifie-t-il que les fonctionnalités d'accessibilité ne peuvent pas être utilisées du tout dans ces applications, ou existe-t-il encore un moyen "générique" d'obtenir le texte sélectionné comme vous l'avez décrit? Avez-vous un exemple de code ou un lien vers des exemples? – Form

+0

L'accessibilité fonctionne sur toutes les applications accessibles. Certaines applications ne sont pas accessibles. Les pires exemples, y compris les deux, ne sont pas susceptibles de prendre en charge d'autres méthodes génériques d'inspection de leurs interfaces utilisateur. Si vous souhaitez les prendre en charge, vous devrez les utiliser avec AppleScript. –

+0

Comme pour les exemples: Non, il ne semble plus y en avoir. Cela dit, si vous pouvez comprendre et utiliser une API Core-Foundation, vous pouvez déterminer ce que vous devez faire à partir des noms de fonctions dans les en-têtes Accessibility. (Le framework dont vous avez besoin, BTW, est ApplicationServices.) –

0

Si vous n'avez pas besoin de texte sélectionné très fréquemment, vous pouvez appuyer sur Commande + C par programmation, puis obtenir le texte sélectionné à partir du Presse-papiers. Mais pendant mon test, cela ne fonctionne que si vous désactivez App Sandbox (impossible de soumettre au Mac App Store).

Voici le code 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) 
    } 
Questions connexes