模拟NSWindow中的鼠标单击

时间:2012-06-15 20:05:38

标签: objective-c macos cocoa

我想在没有实际点击鼠标的情况下模拟鼠标点击Cocoa应用程序,并且*在给定当前鼠标位置的情况下*不必弄清楚哪个视图应该响应点击。

我希望Cocoa框架能够处理哪个视图应该响应,所以我不认为对NSView对象的方法调用是我正在寻找的。也就是说,我认为我需要一个最终调用此方法的方法调用。

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

我在Cocoa文档中读到“将一个NSWindow对象的鼠标事件调度到事件发生的NSView对象”。

行。所以我想知道调用的方法来进行调度。在窗口上调用此方法,然后让框架根据当前鼠标位置确定要调用的NSView。

非常感谢任何帮助。我刚刚开始学习Cocoa框架,所以如果这里的任何术语/ verbage不太正确,我会道歉。

3 个答案:

答案 0 :(得分:4)

很难确切知道实际点击会发生什么样的保真度。例如,您是否希望点击激活应用程序?您是否希望点击将窗口置于顶部?使其成为关键还是主要?如果位置在标题栏中,您是否希望它可能关闭,最小化,缩放或移动窗口?

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

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

我认为你的第一个任务是真正深入思考你想要完​​成什么,所有潜在的陷阱和角落案例,并决定你想如何处理这些。

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

答案 1 :(得分:2)

  

行。所以我想知道调用的方法来进行调度。在窗口上调用此方法,然后让框架根据当前鼠标位置确定要调用的NSView。

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

我对你的问题并不完全清楚所以我不知道你想要做的就是在目标上调用mouseDown:但是,如果你这样做,那将与真正的鼠标点击完全相同。

这是用于提供实时点击的消息。它遍历视图层次结构,自动处理重叠,隐藏消息等,并让视图链中的每个步骤都干预(如果需要)。如果一个视图想要阻止子视图获得点击,那么它就是通过吃hitTest:来实现的,这意味着它会影响你的代码,就像它影响真正的点击一样。 如果点击将被传递,此方法始终会告诉您传递到哪里。

但是,它不一定能够处理无法传递点击的所有原因(acceptedFirstMouse,模态对话框等)。此外,您必须知道窗口和点(在适当的坐标系中),但听起来就像您正在开始的那样。

答案 2 :(得分:1)

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

[self mouseDown: nil];

并在屏幕上显示鼠标位置:

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

    NSPoint mouseLocation = [NSEvent mouseLocation];

    NSLog(@"x:  %f", mouseLocation.x);
    NSLog(@"y:  %f", mouseLocation.y);
}
相关问题