以编程方式将文本输入任何应用程序

时间:2014-09-15 23:32:53

标签: objective-c cocoa scripting-bridge appleevents nsappleeventdescriptor

是否存在概念验证Objective-C可执行文件,它将某些文本输入应用程序,然后使用Apple事件而不是AppleScript单击鼠标?

e.g。

的AppleScript等价物
tell application "System Events"
 tell process "Safari"
  keystroke "Hello World"
  click
 end tell 
end tell

它应该适用于Mac OS X 10.9,最好是面向未来(向后兼容性并不重要)。上下文是我将从另一种语言调用Objective-C代码。

我这样说是因为我读到了:

  

从Mac OS X 10.7开始,低级Cocoa API(NSAppleEventDescriptor)   仍然缺乏必要的功能(例如发送Apple的能力   事件),而高级Cocoa API(脚本桥)太缺陷了   仅限于应用程序风格包装器的可行基础。

  

NSAppleScript只能安全地用在主线程

所以,我的目标是:

  1. 任何申请(按名称或当前)
  2. 任何键盘输入或鼠标
  3. 来自C或Objective-C
  4. 在几百毫秒内
  5. 谢谢!

3 个答案:

答案 0 :(得分:3)

而不是使用AppleEvents,CoreGraphics框架中的CGEvent API< https://developer.apple.com/library/mac/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html>允许您将低级鼠标和键盘事件发布到窗口服务器。

#include <CoreGraphics/CoreGraphics.h>

NSArray *launchedApplications = [[NSWorkspace sharedWorkspace] launchedApplications]; // depreciated but I couldn't find a modern way to get the Carbon PSN
NSPredicate *filter = [NSPredicate predicateWithFormat:@"NSApplicationName = \"TextEdit\""];
NSDictionary *appInfo = [[launchedApplications filteredArrayUsingPredicate:filter] firstObject];
ProcessSerialNumber psn;
psn.highLongOfPSN = [[appInfo objectForKey:@"NSApplicationProcessSerialNumberHigh"] unsignedIntValue];
psn.lowLongOfPSN = [[appInfo objectForKey:@"NSApplicationProcessSerialNumberLow"] unsignedIntValue];

CGEventRef event1 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)6, true); // 'z' key down
CGEventRef event2 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)6, false); // 'z' key up

CGEventPostToPSN(&psn, event1);
CGEventPostToPSN(&psn, event2);

您也可以考虑编写服务&lt; https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/SysServices/introduction.html&gt;,这样您就可以通过应用程序菜单中的“服务”菜单为其他应用程序提供功能。请注意,您甚至可以为服务菜单项指定键盘快捷键。服务通过系统粘贴板工作;如果您只需要将一些预制或生成的数据粘贴到另一个应用程序中,这种方法可能比处理原始窗口服务器事件更容易。

答案 1 :(得分:1)

我不确定这是否是您正在寻找的内容,但您可能对设置NSInvocation对象感兴趣:

- (void)invokeWithTarget:(id)anObject

如果您正在寻找运行某些代码并且模拟&#39;在UX环境中,保存调用并运行它可能很有价值。

(Automator的?)

答案 2 :(得分:1)

实现结果的最佳方法是使用Automator,

请参阅https://developer.apple.com/library/mac/documentation/AppleApplications/Conceptual/AutomatorConcepts/AutomatorConcepts.pdf

如果您想通过ObjectiveC实现这一目标,您需要了解&#34;分布式对象架构&#34;。 通过配对NSPort和NSInvocation,您可以做出惊人的事情,比如跨进程和跨机器方法调用。

以下是该指南 https://developer.apple.com/librarY/prerelease/mac/documentation/Cocoa/Conceptual/DistrObjects/Concepts/architecture.html