1

我正在编写一个应用程序,通过将突出显示的文本复制到 NSPasteboard 的 generalPasteboard 中来响应热键。在这里寻找发送虚拟击键的解决方案后,我发现了这个:如何在objective-c中向活动应用程序发送“Cmd-C”击键,或者告诉应用程序执行复制操作?

我尝试了使用 NSAppleScript 建议的 applescript:

NSLog(@"Hotkey Pressed");
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; 

NSAppleScript *playScript;
playScript = [[NSAppleScript alloc] initWithSource:@"tell application \"System Events\" to keystroke \"c\" using command down"];

if([playScript isCompiled] == NO){
[playScript compileAndReturnError:nil];
}

id exerror = [playScript executeAndReturnError:nil];

if(exerror == nil){
 NSLog(@"Script Failed");
}

它有效,但仅在我第一次按下热键时。随后的每次点击都不会抓取突出显示的文本。generalPasteboard 仍然包含与再次运行脚本之前相同的内容。在我运行代码之前清除 generalPasteboard 是没有用的,因为在尝试读取粘贴板内容时代码会失败。这是日志:

 Pastify[16929:a0b] woooooooo! I'm being CALLED
 Pastify[16929:a0b] Hotkey Pressed
 Pastify[16929:a0b] Error loading /Library/ScriptingAdditions/Adobe Unit Types.osax/Contents/MacOS/Adobe Unit Types:  dlopen(/Library/ScriptingAdditions/Adobe Unit Types.osax/Contents/MacOS/Adobe Unit Types, 262): no suitable image found.  Did find:
    /Library/ScriptingAdditions/Adobe Unit Types.osax/Contents/MacOS/Adobe Unit Types: no matching architecture in universal wrapper
 Pastify: OpenScripting.framework - scripting addition "/Library/ScriptingAdditions/Adobe Unit Types.osax" declares no loadable handlers.
 Pastify[16929:a0b] Size of copiedItems: 1
 Pastify[16929:a0b] Content of paste: 2010-04-19 03:41:04.355 Pastify[16929:a0b] woooooooo! I'm being CALLED
 Pastify[16929:a0b] Hotkey Pressed
 Pastify[16929:a0b] Size of copiedItems: 1
 Pastify[16929:a0b] Content of paste: 2010-04-19 03:41:04.355 Pastify[16929:a0b] woooooooo! I'm being CALLED
 Pastify[16929:a0b] Hotkey Pressed
 Pastify[16929:a0b] Size of copiedItems: 1
 Pastify[16929:a0b] Content of paste: 2010-04-19 03:41:04.355 Pastify[16929:a0b] woooooooo! I'm being CALLED

所以我尝试了下一个建议的解决方案:

 CFRelease(CGEventCreate(NULL));

 CGEventRef event1, event2, event3, event4;
 event1 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)50, true);
 event2 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)8, true);
 event3 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)8, false);
 event4 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)50, false);

 CGEventPost(kCGHIDEventTap, event1);
 CGEventPost(kCGHIDEventTap, event2);
 CGEventPost(kCGHIDEventTap, event3);
 CGEventPost(kCGHIDEventTap, event4);

以上应该发送击键命令+ c,但我得到的只是哔声,粘贴板内容没有改变。

我束手无策 - 任何人都可以启发我了解我缺少什么或指出我忽略了什么如此简单的事情吗?

4

3 回答 3

1

您是否有理由不能为此使用服务?

如果您真的想通过合成事件来做到这一点,最好的办法是发布修改后的键盘事件而不是向下/向上 - 有关更多详细信息,请参阅此问题。

在 Mac OS X 中模拟按键事件

如果这不起作用,那么,你知道在哪里可以找到我 :-)

于 2010-04-19T17:32:30.843 回答
1

只是一个想法...... cmd-c 技巧适用于最前面的应用程序。我怀疑你第一次运行热键来触发这个正确的应用程序是最前面的,cmd-c 工作,然后你的应用程序对粘贴板做一些事情。在第二次运行时,热键被激活,但以前的应用程序不再位于最前面,因此 cmd-c 不起作用。本质上,您将 cmd-c 发送到其他应用程序。也许您的应用程序已经出现在前面或其他一些地方。

为避免此问题,您需要确保您的目标应用程序位于最前面。所以首先你需要一些方法来找出最前面的应用程序是什么,然后在你执行 cmd-c 激活那个应用程序之前。例如,在 applescript 中,如果我想在 Safari 上运行 cmd-c,我会使用:

tell application "Safari" to activate
tell application "System Events" to keystroke "c" using command down
于 2010-04-19T10:05:26.550 回答
0

I really don't understand why you're doing this at all, but if you want to make sure your events go to a specific process, then use the "ToPSN" variant of CGEventPost.

于 2010-04-19T17:45:01.033 回答