2

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

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

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

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

好的。所以我想知道被调用来进行调度的方法。在窗口上调用这个方法,然后让框架在给定当前鼠标位置的情况下确定调用哪个 NSView。

任何帮助将不胜感激。我刚刚开始学习 Cocoa 框架,所以如果这里的任何术语/措辞不完全正确,我深表歉意。

4

3 回答 3

4

很难确切知道您正在寻找多少保真度与实际点击发生的情况。例如,您希望点击激活应用程序吗?您希望单击将窗口带到顶部吗?让它成为关键还是主要?如果该位置在标题栏中,您是否希望它可能关闭、最小化、缩放或移动窗口?

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

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

我认为您的首要任务是真正深入思考您要完成的工作,所有潜在的陷阱和极端情况,并决定您要如何处理这些问题。

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

于 2013-09-21T23:34:02.607 回答
2

好的。所以我想知道被调用来进行调度的方法。在窗口上调用这个方法,然后让框架在给定当前鼠标位置的情况下确定调用哪个 NSView。

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

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

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

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

于 2012-06-15T22:50:46.373 回答
1

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

[self mouseDown: nil];

并在屏幕上获取鼠标位置:

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

    NSPoint mouseLocation = [NSEvent mouseLocation];

    NSLog(@"x:  %f", mouseLocation.x);
    NSLog(@"y:  %f", mouseLocation.y);
}
于 2012-06-15T20:26:47.147 回答