如何通过点击外部来关闭以弹出方式加载的NSWindow?
我想处理鼠标事件,当光标位于具有焦点的模态窗口之外时(但仍在应用程序内)。
答案 0 :(得分:0)
您可以实现NSWindow
的以下委托方法,以获取窗口失去焦点的通知。
- (void)windowDidResignKey:(NSNotification *)notification
在内部检查,如果您的应用程序是最前面的应用程序。如果是,则相应关闭。
答案 1 :(得分:0)
虽然应用程序处于模态运行循环中,但它不会响应任何应用程序 其他事件(包括鼠标,键盘或窗口关闭事件) 除非它们与窗口相关联。它也不会执行 任何与之无关的任务(如射击计时器) 模态运行循环。
您可以使用nextEventMatchingMask:untilDate:inMode:dequeue:
方法。这可以在模态循环中使用。
NSWindow和NSApplication都定义了该方法 nextEventMatchingMask:untilDate:inMode:dequeue:,它允许一个 object用于从事件队列中检索特定类型的事件。
答案 2 :(得分:0)
如上所述,有必要覆盖[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]方法。在我的情况下(插件)我必须使用从NSApplication派生的第三方未知类的现有实例。我不能从中派生出一个新类。因此,我使用method_exchangeImplementations
将上面的命名方法与我自己的实现交换
+ (void)hijack
{
Class appClass = [NSApplication class];
Method originalMethod = class_getInstanceMethod(appClass, @selector(nextEventMatchingMask:untilDate:inMode:dequeue:));
Method categoryMethod = class_getInstanceMethod(appClass, @selector(my_nextEventMatchingMask:untilDate:inMode:dequeue:));
method_exchangeImplementations(originalMethod, categoryMethod);
}
如下所示:
- (NSEvent *)my_nextEventMatchingMask:(NSUInteger)mask untilDate:(NSDate *)expiration inMode:(NSString *)mode dequeue:(BOOL)deqFlag
{
NSEvent *event = [self my_nextEventMatchingMask:mask untilDate:expiration inMode:mode dequeue:deqFlag];
NSEventType type = [event type]; // 0 if event is nil
if (type == NSLeftMouseDown || type == NSRightMouseDown)
{
if ([self modalWindow] != nil && [event window] != [self modalWindow])
{
[self stopModalWithCode:NSModalResponseCancel];
event = nil;
}
}
return event;
}
最后调用模态窗口如下:
[NSApplication hijack];
[NSApp runModalForWindow:window];
[NSApplication hijack];
显然,如果你可以覆盖NSApplication,那么你不需要定义和调用hijack
方法。