可可虚拟按键痛
我正在编写一个应用程序,通过将突出显示的文本复制到 NSPasteboard 的 GeneralPasteboard 中来响应热键。在这里寻找发送虚拟击键的解决方案后,我发现了这个: 如何向 Objective-c 中的活动应用程序发送“Cmd-C”击键,或告诉应用程序执行复制操作?
I尝试了 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);
上面应该发送击键 Command + c,但我得到的只是一声蜂鸣声,并且粘贴板内容没有更改。
我束手无策 - 谁能启发我,让我明白我错过了什么,或者指出我在如此简单的事情上忽略了什么?
I'm writing an application to respond on a hotkey by copying highlighted text into NSPasteboard's generalPasteboard. After looking around here for a solution for sending virtual keystrokes, I found this: How to send a "Cmd-C" keystroke to the active application in objective-c, or tell the application to do a copy operation?
I tried the applescript suggested with NSAppleScript:
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");
}
It works, but only on the first time I hit the hotkey. Each subsequent hit will not grab the highlighted text. The generalPasteboard still contains the same contents as before the script is run again. Clearing the generalPasteboard before I run the code is no use, because then the code fails when attempting to read the pasteboard contents. Here's the log:
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
So I tried the next suggested solution:
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);
The above should send the keystrokes Command + c, but all I get is a beep, and the pasteboard contents are unchanged.
I'm at wits end - can anyone enlighten me as to what I'm missing or point me out to what I'm overlooking for something so simple?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您是否有理由无法为此使用服务?
如果您确实想通过合成事件来做到这一点,那么最好的选择是发布修改后的键盘事件而不是向下/向上 - 有关更多详细信息,请参阅此问题。
在 Mac OS X 中模拟按键事件
如果这不起作用,好吧,你知道在哪里可以找到我:-)
Is there a reason you can't use a service for this?
If you really want to do it by synthesizing events, your best bet is to post a modified keyboard event rather than down/up - see this question for more details.
Simulating key press events in Mac OS X
If that doesn't work, well, you know where to find me :-)
只是一个想法... cmd-c 技巧适用于最前面的应用程序。我怀疑,第一次运行热键来触发此操作时,正确的应用程序位于最前面,cmd-c 有效,然后您的应用程序会对粘贴板执行某些操作。第二次运行时,热键被激活,但之前的应用程序不再位于最前面,因此 cmd-c 不起作用。本质上,您正在将 cmd-c 发送到其他应用程序。也许您的应用程序已经出现在前面或其他一些。
为了避免此问题,您需要确保您的目标应用程序位于最前面。因此,首先您需要某种方法来找出最前面的应用程序是什么,然后在执行 cmd-c 之前激活该应用程序。例如,在 applescript 中,如果我想在 Safari 上运行 cmd-c,我会使用:
Just a thought... the cmd-c trick works on the frontmost application. I suspect that the first time you run the hotkey to trigger this that the proper application is frontmost, cmd-c works, then your application does something with the pasteboard. On second run the hotkey is activated but the previous application is no longer frontmost so cmd-c does not work. In essence you're sending cmd-c to some other application. Maybe your application has come to the front or some other.
To avoid this problem you need to make sure the application you are targeting is frontmost. So first you need some way to find out what the frontmost application is and then just before you perform cmd-c activate that application. For example in applescript if I wanted to run cmd-c on Safari I would use:
我真的不明白你为什么要这样做,但如果你想确保你的事件进入特定的进程,那么使用 CGEventPost 的“ToPSN”变体。
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.