点击按钮,而不是提升窗口

5 cocoa objective-c nsevent nsapplication

iTunes迷你播放器(仅举一个例子)支持点击,当使用播放/暂停和音量控制时,应用程序不会被带到前面.

这是怎么做到的?

我一直在查看Apple的文档,并在Cocoa事件处理指南,事件调度中指出:

某些事件(其中许多是由Application Kit定义的(类型为NSAppKitDefined))与由窗口或应用程序对象本身控制的操作有关.这些事件的示例是与激活,停用,隐藏和显示应用程序相关的事件.NSApp在其调度例程的早期过滤掉这些事件并自行处理它们.

因此,从我有限的理解(如何一个事件进入Cocoa,应用程序)子类化NSApplication和覆盖 - (void)sendEvent:(NSEvent *)theEvent应该捕获每个鼠标和键盘事件,但仍然,窗口是单击时引发的.因此,在NSApplication看到事件之前窗口会被提升,或者我错过了其他内容.

通过重新创建它看了Matt Gallagher的Demystifying NSApplication,不幸的是Matt没有覆盖事件队列,所以除此之外,我很难过.

任何帮助将不胜感激,谢谢.

编辑补充:劳埃德休息室找到一个帖子,他在讲述同样的问题并链接到CocoaBuilder的帖子,首先捕获右键.我正在尝试在那里提供的代码,在一些摆弄并重新激活[theEvent类型]的NSLog之后,鼠标左键活动被捕获.

现在,左键单击窗口将其向前移动会生成一系列事件类型13, 1, 13,这些类型分别是NSAppKitDefined,NSLeftMouseDown和NSAppKitDefined.我可以过滤掉它们或找到它们的去向吗?

小智 3

这并不是我一直在寻找的答案,但目前它的效果足够好。通过子类化NSView并实现以下方法,该视图可以充当按钮。

- (void)mouseDown:(NSEvent *)theEvent {
    [NSApp preventWindowOrdering];
//  [self setNeedsDisplay:YES];
}

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent {
    return YES;
}

- (BOOL)shouldDelayWindowOrderingForEvent:(NSEvent *)theEvent {
    return YES;
}
Run Code Online (Sandbox Code Playgroud)

不需要其他任何东西,仅此而已。当然,这绕过了我想保留的所有 NSButton 优点,我必须设计然后负责绘制和更新按钮状态,但我很高兴得到答案。