编辑 - 没有得到太多的输入,所以这里是瘦。我正在向PSN发布键盘事件。然后我切换到另一个窗口,发布更多事件(这次是会话级别)并切换回第一个窗口。当我再次开始向PSN发帖时,没有任何反应。直到我移动鼠标或滚轮。为什么会出现这种情况,我该如何处理它(如果没有解决的话)?
原创 - 如果我设置一个将某些键盘事件发布到PSN的循环,我发现除了首次启动时它工作正常。当我用手动鼠标做某事时,事件似乎只会发布 - 即使只是略微移动它。如果有帮助的话,这是详细信息。
外部应用程序有一个文本行列表框,我通过发布复制命令(并检查粘贴板)来阅读。不幸的是,这是获取此文本的唯一方法。
有时,应用程序将焦点从列表中拉开,我可以检测到。发生这种情况时,最可靠的返回焦点的方法是发送鼠标事件以单击列表正上方的文本字段,然后发送“tab”键盘事件以将焦点移动到列表上。
因此,在启动时,循环运行正常,向下滚动列表并复制文本。当焦点移开时,其被检测到正常,并且发送事件以将焦点移回列表。但似乎没有任何事情发生。循环继续检测焦点是否已更改,但只有在移动鼠标时事件才会起作用。甚至只需使用滚轮。奇怪。
一旦这种情况第一次发生,它就能正常工作 - 每次焦点移动时,PSN事件都会将其切换回来,而我根本不需要做任何事情。
这是在循环中运行的代码 - 经过验证工作:
//copy to pasteboard - CMD-V
e3 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)8, true);
CGEventSetFlags(e3, kCGEventFlagMaskCommand);
CGEventPostToPSN(&psn, e3);
CFRelease(e3);
e4 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)8, false);
CGEventPostToPSN(&psn, e4);
CFRelease(e4);
//move cursor down
e1 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)125, true);
CGEventPostToPSN(&psn, e1);
CFRelease(e1);
e2 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)125, false);
CGEventPostToPSN(&psn, e2);
CFRelease(e2);
这里是我切换焦点的地方,也是工作(除非首次需要):
//click in text input box - point is derived earlier
e6 = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseDown, point, 0);
CGEventPostToPSN(&psn, e6);
CFRelease(e6);
e7 = CGEventCreateMouseEvent(NULL, kCGEventLeftMouseUp, point, 0);
CGEventPostToPSN(&psn, e7);
CFRelease(e7);
//press tab key to move to chat log table
CGEventRef e = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)48, true);
//CGEventPost(kCGSessionEventTap, e);
CGEventPostToPSN(&psn, e);
CFRelease(e);
CGEventRef e11 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)48, false);
CGEventPostToPSN(&psn, e11);
CFRelease(e11);
答案 0 :(得分:2)
嘿,我知道这不是你想听到的,但是对于这种事情,applescript工作得更好 - 通过发布复制命令来阅读文本字段,通过向附近的项目发送点击事件来设置重点,然后发送标签事件 - 它真的不是'最好的方法。
模拟事件的问题在于生成它们并不是全部。如果目标应用程序正确解释它们,它们只会成为“事件”。你知道目标应用程序是否是一个可可应用程序?
例如,在第二段代码中,您将创建4个事件。目标应用程序需要运行它的事件处理循环,您无法控制,并检查排队的事件。如果它这样做,它会发现同时按下鼠标,鼠标按下,按下键,按键。你希望它能够将这些同时发生的事件解释为鼠标点击,然后是一个按键......但是谁会这么说呢?
您可以通过添加刷新事件队列的组合,将目标应用程序运行到运行它的runloop 来实现此功能,然后投入一些在模拟事件之间暂停,并摆弄事件时间戳 - 但它可能不会那么可靠。
在Applescript中,您可以通过
获取另一个应用程序中表格第3行的文本tell application "System Events"
tell process targetAppName
set frontmost to true
tell window named windowTitle
tell table 1
set value of attribute "AXFocused" to true
set txtField to first text field of row 3
return value of txtField
end tell
end tell
end tell
end tell
从cocoa App可以执行String作为Applescript,可以在不同的脚本中调用函数,传递变量,返回值等。
答案 1 :(得分:1)
尝试以这种方式创建输入源,而不是使用null CGEventSourceRef创建事件:
CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
基于此mailing list message,这似乎是使用CGEventCreateXXXEvent发布事件成功的秘诀。谷歌搜索显示许多开发人员遇到了这方面的问题,但这是我发现的一个成功的帖子,并且一个正确的CGEventSourceRef(而不是NULL)似乎是这个例子与其他所有人之间的差异我找到了。它解决了我发布键盘事件的问题。