2012-06-15 88 views
2

我想在没有实际点击鼠标的情况下模拟Cocoa应用程序上的鼠标点击,并且*不必知道在当前鼠标位置的情况下哪个视图应该响应点击。在NSWindow中模拟鼠标点击

我想Cocoa框架来处理搞清楚哪些观点应该作出回应,所以我不认为一个的NSView对象上的方法调用就是我要找的。也就是说,我想我需要一个方法调用,最终调用这个方法。

我现在有通过点击鼠标在特定的全局位置,使用CGEventCreateMouseEvent和CGEventPost这个工作。但是,这种技术实际上点击了鼠标。所以这是有效的,但我并不完全满意这种行为。例如,如果我在调用CGEventPost时按住键盘上的某个键,则该键将被包装到事件中。另外,如果我将另一个进程的窗口移动到我想要模拟点击的窗口上,那么CGEventPost方法将在该窗口中单击鼠标。也就是说,它在全球范围内行动,跨越流程。我想要一种可以在单个窗口上工作的技术。 NSWindow对象上可能有?

我在Cocoa文档中读到“鼠标事件由NSWindow对象分派给发生事件的NSView对象”。

好的。所以我想知道调用的方法。在窗口中调用这个方法,然后让框架指定哪个NSView调用给定当前鼠标位置。

任何帮助将不胜感激。我刚刚开始学习Cocoa框架,所以我很抱歉如果有任何术语/动词不完全正确。

+2

[' - [NSApplication sendEvent:]'](http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html)实质上是输入事件的入口点;从那里(通常)传递到窗口。也就是说,你试图在“模拟”和“实际”点击鼠标之间的区别并不清楚。您试图避免的“CGEvent”过程有哪些功能? (例如,物理鼠标设备中没有移动按钮的伺服器,这就是我所称的“实际”点击。) –

+0

已编辑。 Thx为您的评论。 –

+0

@JoshCaswell这看起来很不错,但我无法实现。我会发布代码,但是它使用Objective C桥编写在Clozure中,因此解析可能会有点麻烦。我找不到任何使用sendEvent模拟鼠标点击的例子。你有机会吗? –

回答

4

很难确切知道您要寻找多少保真度,以及实际点击会发生什么。例如,你想要点击来激活应用程序吗?你想点击一下窗口到顶部?为了让它成为关键还是主要?如果位置在标题栏中,您是否希望它可能关闭,最小化,缩放或移动窗口?

正如John Caswell指出的那样,如果您传递一个适当构造的NSEvent-[NSApplication sendEvent:],它将精确地模拟真实事件的处理过程。在大多数情况下,NSApplication将把事件转发到事件窗口及其-[NSWindow sendEvent:]方法。如果您想避免NSApplication做其他事情,则可以直接发送到窗口的-sendEvent:方法。但是这可能会打败一些理想的行为,具体取决于你的愿望。

如果点击的窗口或视图的响应是运行内部事件跟踪循环,会发生什么?这将是同步的;也就是说,调用-sendEvent:的代码在该循环完成之后才会得到控制权,并且如果您无法传递后续事件,该代码可能无法完成。事实上,这样的循环将通过-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]寻找随后的事件,所以如果你的综合事件不在队列中,它们将不会被看到。因此,对真实事件处理的更好模拟可能需要您使用-[NSApplication postEvent:atStart:]将事件(鼠标向下,鼠标拖动,鼠标移动)发布到队列中。

我认为你的首要任务是深入思考你要完成的任务,所有潜在的陷阱和案例,并决定如何处理这些问题。

关于CGEvent...的东西,您可以使用CGEventPostToPSN()将事件发布到特定进程,即使它们位于目标窗口的前方,它也不会点击其他应用程序的窗口。但是,它仍然可以点击目标应用程序中的其他窗口。

1

您可以通过调用mouseDown:这样模拟鼠标点击:

[self mouseDown: nil]; 

而且在屏幕上获得鼠标位置:

-(void)mouseDown:(NSEvent *)theEvent { 

    NSPoint mouseLocation = [NSEvent mouseLocation]; 

    NSLog(@"x: %f", mouseLocation.x); 
    NSLog(@"y: %f", mouseLocation.y); 
} 
+0

这需要已经知道鼠标事件的正确目标。 –

+0

@JoshCaswell你是指知道鼠标事件的正确目标是什么? –

+0

这看起来像是正确的方向,但我认为我需要为鼠标单击构建适当的NSEvent对象。该代码应该有鼠标位置,是的? –

2

确定。所以我想知道调用的方法。在窗口中调用这个方法,然后让框架指定哪个NSView调用给定当前鼠标位置。

NSView *target = [[theWindow contentView] hitTest:thePoint]; 

我不是你的问题完全清楚,所以我不知道,如果你想要做的是再调用鼠标按下:目标。但是,如果你这样做了,那几乎和真正的鼠标点击一样。

这是用于提供实时点击的消息。它遍历视图层次结构,自动处理重叠,隐藏的消息等,并让视图链中的每一步都可以干预。如果一个视图想要阻止子视图获得点击,那么通过使用hitTest:来做到这一点,这意味着它会以与实际点击相同的方式影响您的代码。 如果点击将被发送,该方法总是告诉你其中它将被发送。

然而,这并不一定处理的点击可能无法传递(acceptsFirstMouse,模态对话框等)的所有原因。此外,你必须知道窗口和点(在适当的坐标系中),但听起来你就是这样开始的。

+0

谢谢你。这看起来像一个简单的方法。将尽快测试,并发布结果。 –